假设有两个方法 methodA()
和 methodB()
从不同的线程调用。我想要的是,当调用 methodA()
时,调用 methodB()
的线程将被阻塞,直到 methodA()
完成,并且另一边。这可以通过信号量轻松实现:
private Semaphore semaphore = new Semaphore(1, true);
public void methodA() {//ignored try catch finally
semaphore.acquire();
//do stuff
semaphore.release();
}
public void methodB() {
semaphore.acquire();
//do stuff
semaphore.release();
}
但问题是我希望多个线程同时执行 methodA()
或 methodB()
。 多个线程应该能够同时执行methodA()
,只要没有人执行methodB()
;上述解决方案在这种情况下不起作用,因为如果一个线程执行 methodA()
,则即使没有线程执行 methodB,其他线程也无法执行
.methodA()
()
我能想到的任何其他解决方案要么需要方法中的同步,要么执行其他操作,如果没有线程执行另一个方法,则不允许多个线程执行单个方法。
最佳答案
这种情况非常像十字路口的红绿灯。要么道路 A 通过,要么通过道路 B,但不能同时通过。
假设我们有一个 TrafficLight
类,它的作用有点像 Semaphore
,它监视两条道路“A”和“B”。想要传递“A”的线程可以请求“A”的权限,并且应被授予该权限,或者如果“B”权限尚未释放则阻塞,反之亦然。
过去我做过这样一个TrafficLight
类作为练习(实际上可以监控2个以上的状态):
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class TrafficLight<T> {
private ReentrantLock lock = new ReentrantLock(true);
private Condition switched = lock.newCondition();
private int registered;
private int maxBeforeYield = 20;
private T state;
public void acquire(T t) throws InterruptedException {
lock.lock();
try {
while ((state != null && !state.equals(t)) || maxBeforeYield == 0) {
switched.await();
}
if (state == null) {
state = t;
}
registered++;
maxBeforeYield--;
} finally {
lock.unlock();
}
}
public void release() {
lock.lock();
try {
registered--;
if (registered == 0) {
state = null;
maxBeforeYield = 20;
switched.signalAll();
}
} finally {
lock.unlock();
}
}
}
请注意 maxBeforeYield
:TrafficLight 可能遇到的一个问题是,对“A”的请求数量如此之大,以至于对“B”的请求永远没有机会。因此,TrafficLight 对请求进行计数,在多次请求 (maxBeforeYield
) 后,它也开始阻止“A”请求,然后很好地等待,直到返回所有权限,然后给另一个状态一个机会, ReentrantLock
需要公平,以确保“方向”切换,除非仅阻止同一方向的请求。
鉴于此 TrafficLight
类,您可以将代码更改为:
private TrafficLight<String> trafficLight = new TrafficLight<>();
public void methodA() {//ignored try catch finally
trafficLight.acquire("A");
//do stuff
trafficLight.release();
}
public void methodB() {
trafficLight.acquire("B");
//do stuff
trafficLight.release();
}
关于java - 如果从另一个线程调用另一个方法,则多个线程调用一个方法,同时阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23227529/