我有两种方法:a()
和b()
. 虽然我对多个线程同时访问任何方法感到满意(这是可取的),但我不希望任何线程在执行时a()
进入b()
。我怎么做?
编辑 1
假设有 4 个线程并且Thread 1
正在访问A()
. 我想要的是所有 4 个线程都不应该使用B()
.
我有两种方法:a()
和b()
. 虽然我对多个线程同时访问任何方法感到满意(这是可取的),但我不希望任何线程在执行时a()
进入b()
。我怎么做?
假设有 4 个线程并且Thread 1
正在访问A()
. 我想要的是所有 4 个线程都不应该使用B()
.
检查底部的更新- 我认为这种方法行不通。留下它以供参考。
您可以使用信号量:
b()
,则试图执行的线程a()
将阻塞,直到 的执行b()
结束。b()
并且第二个线程尝试运行b()
,它将能够a()
在b()
未执行的情况下执行,则两者都将运行注意:一旦一个线程进入a()
并通过了“信号量测试”,另一个线程可以b()
在结束前开始运行a()
该原理应该有效,但我尚未对其进行测试。
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()
但绝不应该并行运行)。在这种情况下,您可以对 2 个信号量和.a()
b()
inA
inB
更新 => 错误
正如@yshavit 在对另一个答案的评论中指出的那样,在以下情况下,代码中存在竞争条件:
a()
并获取inB
b()
但获取失败inB
inB
a()
并设法获取inB
b()
似乎仅使用 Sempahores 无法实现这一点。这个答案提供了一个更好的解决方案。
为简单起见省略了异常处理:
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();
}
}
}
java.util.concurrent.locks是一个包含多个锁的 Java 包
in b()
, 对同一个锁做同样的事情
如果您想处理不对称行为,您可以使用ReadWriteLock, a() 是读取器, b() 是写入器:几个 b() 锁,但几个 a() 没有。