gpt4 book ai didi

java - 如果从另一个线程调用另一个方法,则多个线程调用一个方法,同时阻塞

转载 作者:行者123 更新时间:2023-12-01 13:06:24 25 4
gpt4 key购买 nike

假设有两个方法 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com