我有两种方法:a()
和b()
。虽然我很好地同时访问任何方法的多个线程(这是可取的),但我不希望任何线程在执行a()
时输入b()
。
我该怎么做?
假设有4个主题,Thread 1
正在访问A()
。我想要的是4个线程中的所有线程都不应该使用B()
。
答案 0 :(得分:6)
检查底部的更新 - 我不认为这种方法可行。留待它获取信息。
您可以使用Semaphore:
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()
并行,但a()
和b()
不应该并行运行。在这种情况下,您可以使用2个信号量inA
和inB
使用相同的逻辑。
UPDATE => BUG 强>
正如@yshavit在对another answer的评论中指出的那样,在以下场景中代码中存在竞争条件:
a()
并获取inB
b()
,无法获取inB
inB
a()
并设法获取inB
,尽管T2正在运行b()
似乎仅凭Sempahores无法实现。 This answer gives更好的解决方案。
答案 1 :(得分:3)
为简单起见,省略了异常处理:
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();
}
}
}
答案 2 :(得分:1)
java.util.concurrent.locks是一个包含多个锁的Java包
<{1}}中的<a()
,take a lock和release it {/ 1}}
在a()
中的,使用相同的锁
执行相同的操作如果你想处理非对称行为,你可以使用ReadWriteLock,a()是读者,b()是编者:几个b()锁,但是几个a()没有。