Java 如果从另一个线程调用另一个方法,则多个线程在阻塞时调用该方法
假设有两个方法Java 如果从另一个线程调用另一个方法,则多个线程在阻塞时调用该方法,java,multithreading,concurrency,Java,Multithreading,Concurrency,假设有两个方法methodA()和methodB()是从不同的线程调用的。我想要的是,当调用methodA()时,调用methodB()的线程将被阻塞,直到methodA()完成,反之亦然。这可以通过信号量轻松实现: private Semaphore semaphore = new Semaphore(1, true); public void methodA() {//ignored try catch finally semaphore.acquire(); //do s
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()
则没有其他线程可以执行methodA()
,即使没有线程执行methodB()
我能想到的任何其他解决方案都需要在方法中进行同步,或者如果没有线程执行另一个方法,则不允许多个线程执行另一个方法。这种情况非常类似于十字路口的交通灯。A路或B路都可以通过,但决不能同时通过 假设我们有一个
TrafficLight
类,它的行为有点像一个信号灯,它监视两条道路“a”和“B”。想要通过“A”的线程可以请求对“A”的许可,并应被授予该许可,如果“B”许可未被释放,则阻止,反之亦然
在过去,我做过这样一个TrafficLight
课程作为练习(实际上可以监控两个以上的状态):
听起来您需要读写器锁(例如java.util.concurrent.locks.ReentrantReadWriteLock)。它允许任意数量的“读卡器”同时使用资源,或者只允许一个“写卡器”使用资源,但不能同时使用两者
一个好的实现,如Java版本,由于需要提供“公平性”,会稍微复杂一些。例如,它不能“饥饿”一个想要资源的编写器,即使有如此多的读卡器,资源从来没有空闲的时候。您是否正试图特别避免同步?
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();
}
}
}
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();
}