为什么与信号量解决方案会合不能泛化(我们改用屏障)?



对于会合问题,我们需要同步两个线程,这是一个经典的解决方案:

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,那将非常简单,因为它为你做这种事情。 但是对于一般情况,您将如何做到这一点并自己编写? 您可以执行类似于CountdownLatchCyclicBarrier所做的事情。

保持预期各方数量的计数,在他们接近障碍时减少它,然后在减少计数为 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();

相关内容

最新更新