对于会合问题,我们需要同步两个线程,这是一个经典的解决方案:
aArrived = S(0);
bArrived = S(0);
线程 A:
while(true) {
doSomething();
aArrived.signal();
bArrived.wait();
}
线程 B:
while(true) {
doSomething();
bArrived.signal();
aArrived.wait();
}
这适用于两个线程,但是 N 个线程呢?对于 N=3,我们可以实现如下:
线程A(其他线程是对称的):
while(true) {
doSomething();
aArrived.signal();
aArrived.signal();
bArrived.wait();
cArrived.wait();
}
我找到的所有来源都只是说:"再次考虑第 3.2 节中的会合问题。我们介绍的解决方案的一个限制是它不适用于两个以上的线程",或者"之前介绍的解决方案不适用于两个以上的线程。
(顺便说一下,这里介绍的广义解决方案可能不是最佳的,因为它会对 N 个线程使用 N 个信号量......我只是好奇是否有人遇到此解决方案不适用于 N>2 线程的情况?
如果你在Java中使用CyclicBarrier
,那将非常简单,因为它为你做这种事情。 但是对于一般情况,您将如何做到这一点并自己编写? 您可以执行类似于CountdownLatch
或CyclicBarrier
所做的事情。
保持预期各方数量的计数,在他们接近障碍时减少它,然后在减少计数为 0 时通知所有人。 例如:(这是令人难以置信的简化)。
class CountdownBarrier {
private int numberOfParties;
private final Object lock = new Object();
public CountdownBarrier(int numberOfParties){ this.numberOfParties = ..}
public void arriveAndAwait(){
synchronized(lock){
if(--numberOfParties == 0)
lock.notifyAll();
while(numberOfParties != 0)
lock.wait();
}
}
}
然后
CountdownBarrier barrier = new CountdownBarrier(3);
Thread A:
barrier.arriveAndAwait();
Thread B:
barrier.arriveAndAwait();
Thread C:
barrier.arriveAndAwait(); // assuming time progresses downward, this arriveAndAwait will notify all threads to wake up and continue.
在 Java 中也可以使用
CyclicBarrier#await();
或
CountdownLatch#countDown(); // then
CountdownLatch#await();