Java中的互斥方法执行

Java中的互斥方法执行,java,multithreading,synchronized,Java,Multithreading,Synchronized,我有两种方法:a()和b()。虽然我可以让多个线程同时访问任何方法(这是可取的),但我不希望任何线程在执行b()时进入a()。 我该怎么做 编辑1 假设有4个线程,线程1正在访问A()。我想要的是,所有4个线程都不应该使用B()。留作参考 您可以使用: 如果线程位于b()中,则尝试执行a()的线程将阻塞,直到b()的执行结束 如果一个线程在b()中,而另一个线程试图运行b()它将能够 如果两个线程执行a(),而b()未执行,则两个线程都将运行 注意:一旦一个线程在a()中并通过了“信号量测

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

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


您可以使用:

  • 如果线程位于
    b()
    中,则尝试执行
    a()
    的线程将阻塞,直到
    b()
    的执行结束
  • 如果一个线程在
    b()
    中,而另一个线程试图运行
    b()
    它将能够
  • 如果两个线程执行
    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();
    }
}
编辑

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


更新=>BUG

正如@yshavit在对的注释中指出的,在以下场景中,代码中存在竞争条件:

  • T1运行
    a()
    并获取
    inB
  • T2运行
    b()
  • T1发布
    inB
  • T3运行
    a()
    并设法获取
    inB
    ,而T2运行
    b()
这似乎仅仅用Sempahores是无法实现的。更好的解决方案。

是一个包含多个锁的Java包

a()
中,以及
a()的末尾

b()
中,对相同的锁执行相同的操作


如果要处理不对称行为,可以使用a,a()是读卡器,b()是写卡器:几个b()锁,但几个a()锁不锁

为简单起见,建议使用异常处理:

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();
    }
  }
}

a()
的末尾调用
b()
我想这不是问题所在。在使用
b()
时,不允许执行线程
a()
b()
是否修改基础资源?你在找一个吗?
我不希望任何线程在执行b()时输入a()
意味着如果线程a正在访问
a()
,那么你不希望线程b使用
b()
?这就是你想要的吗?如果是,请告诉我们你到底想做什么。也许我们可以帮你。我闻到,你的代码中有可疑的东西,那么当执行
a()
时会发生什么情况呢?是否允许任何其他线程输入
b()
?这是synchronize将执行的操作,而不是OP正在查找的操作。请查看对我的评论的答复?我不明白OP想做什么。如果线程A正在访问A(),那么OP不希望线程B使用B(),如果第一个线程通过
A()
的信号量锁定和解锁会怎么样。上下文切换。线程2跳入
b()
。它开始执行
b()
。执行上下文开关
A()
。这不正是我们想要避免的情况吗?a和b是并行执行的?@coding.mof我在回答中包括了这个案例。最初的问题是:“我不希望任何线程在执行b()时输入a()。因此,一旦您输入了
a()
,因为没有线程运行
b()
,您就没事了。