【问题标题】:Mutually exclusive method execution in JavaJava中的互斥方法执行
【发布时间】:2012-11-10 09:07:31
【问题描述】:

我有两种方法:a()b()。虽然我对多个线程同时访问任何方法感到满意(这是可取的),但我不希望任何线程在执行b() 时进入a()。 我该怎么做?

编辑 1

假设有 4 个线程,Thread 1 正在访问 A()。我想要的是所有 4 个线程都不应该使用B()

【问题讨论】:

  • a()末尾调用b()
  • 我不认为这是被问到的。
  • 在使用b() 时不允许执行线程a()b() 是否修改底层资源?您在寻找ReadWriteLock 吗?
  • I do not want any threads to enter a() while b() is being executed 意味着 如果线程A正在访问a(),那么你不希望线程B使用b() ? 这就是你想要的吗?如果是,请告诉我们您到底想做什么。也许我们可以帮助你。我闻到了,您的代码中发生了一些可疑的事情
  • 那么当a() 被执行时呢?是否允许任何其他线程进入b()

标签: java multithreading synchronized


【解决方案1】:

检查底部的更新 - 我认为这种方法行不通。留作参考。


你可以使用Semaphore:

  • 如果线程在b() 中,则尝试执行a() 的线程将阻塞,直到b() 的执行结束。
  • 如果一个线程在b() 中并且第二个线程尝试运行b(),它将能够
  • 如果有 2 个线程执行 a()b() 没有被执行,两个线程都会运行

注意:一旦一个线程在a()并通过了“信号量测试”,另一个线程可以在a()结束之前开始运行b()

原理应该可以,但我没有测试过。

private final Semaphore inB = new Semaphore(1);

public void a() throws InterruptedException {
    inB.acquire(); //blocks until no thread is in b any longer
    //now we are good to go and execute a()
    //release the semaphore immediately for other threads who want to run a()
    inB.release(); 
    //rest of your code here
}
public void b() {
    //does not block to allow 2 thread running b() simultaneously
    boolean needToRelease = inB.tryAcquire(); 
    //rest of your code
    //if the permit was acquired, release it to allow threads to run a()
    if (needToRelease) {
        inB.release();
    }
}

编辑

您的意图不明确并且您的问题已被编辑,因为您的一个 cmets 说您希望 a()b() 互斥(许多线程可以并行运行 a()b(),但a()b() 永远不应该并行运行)。在这种情况下,您可以对 2 个信号量 inAinB 使用相同的逻辑。


更新 => 错误

正如@yshavit 在对another answer 的评论中指出的那样,在以下场景中的代码中存在竞争条件:

  • T1 运行a() 并获取inB
  • T2 运行b() 并未能获取inB
  • T1 发布inB
  • T3 运行 a() 并设法获取 inB 尽管 T2 正在运行 b()

这似乎无法仅通过 Sempahores 实现。 This answer gives 更好的解决方案。

【讨论】:

  • 能否请您查看对我的评论的回复?我不明白 OP 想要做什么。 如果线程 A 正在访问 a(),那么 OP 不希望线程 B 使用 b()
  • 如果第一个线程通过a()的信号量锁定和解锁怎么办。上下文切换。线程 2 跳转到 b()。它开始执行b()。上下文切换A() 被执行。这不正是我们想要避免的情况吗? a 和 b 是并行执行的吗?
  • @coding.mof 我在回答中包含了这个案例。最初的问题是:“我不希望任何线程在执行 b() 时进入 a()”。所以一旦你输入a(),因为没有线程在运行b(),你就没事了。
【解决方案2】:

为简单起见省略了异常处理:

public class Test {
  private final Object lock = new Object();
  private int counterA;
  private int counterB;

  public void a() {
    synchronized(lock) {
      while(counterB > 0) {
        lock.wait();
      }
      ++counterA;
    }

    // do work

    synchronized(lock) {
      --counterA;
      lock.notifyAll();
    }
  }

  public void b() {
    synchronized(lock) {
      while(counterA > 0) {
        lock.wait();
      }
      ++counterB;
    }

    // do work

    synchronized(lock) {
      --counterB;
      lock.notifyAll();
    }
  }
}

【讨论】:

    【解决方案3】:

    java.util.concurrent.locks 是一个包含多个锁的 Java 包

    a()take a lockrelease it 的末尾a()

    b(),对同一个锁做同样的事情

    如果你想处理不对称行为,你可以使用ReadWriteLock,a() 是读取器,b() 是写入器:有几个 b() 锁,但有几个 a() 没有。

    【讨论】:

    • 这就是同步将做的,而这不是 OP 正在寻找的
    猜你喜欢
    • 1970-01-01
    • 2012-12-17
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    相关资源
    最近更新 更多