2013-04-01 51 views
0

问题如下,因为只有使用down()调用屏障才能等待n个线程到达,然后在关键区域中一起执行所有n个线程现在我该如何通知barrier.down这个线程,它现在可以继续。我尝试加notifyAll()阶段2()并且不起作用。帮帮我? :)使用信号量在java中实现一个循环屏障

public class cyclicBarrier { 
    private int n; 
    private int count; 
    private semaphore mutex; 
    private semaphore turnstile; 
    private semaphore turnstile2; 

    public cyclicBarrier(int n){ 
     this.n = n; 
     this.count = 0; 
     this.mutex = new semaphore(1); 
     this.turnstile = new semaphore(0); 
     this.turnstile2 = new semaphore(0); 
    } 

    public synchronized void down() throws InterruptedException{ 
     this.phase1(); //waits for n threads to arrive 
     this.phase2(); //waits for n threads to execute 
    } 

    private synchronized void phase1() throws InterruptedException { 
     this.mutex.down(); 
     this.count++; 
     if(this.count == this.n){ 
      for(int i = 0; i < this.n; i++){ 
       this.turnstile.signal(); //when n threads received then move on to phase 2 
      } 
     } 
     this.mutex.signal(); 
     this.turnstile.down(); //keeps waiting till I get n threads 
    } 

    private synchronized void phase2() throws InterruptedException { 
     this.mutex.down(); 
     this.count--; 
     if(this.count == 0){ 
      for(int i = 0; i < this.n; i++){ 
       this.turnstile2.signal(); //reset the barrier for reuse 
      } 
     } 
     this.mutex.signal(); 
     this.turnstile2.down(); //keeps waiting till n threads get executed 
    } 
} 


public class semaphore { 
    private int counter; 

    public semaphore(int number){ 
     if (number > 0) { 
      this.counter = number; 
     } 
    } 

    public synchronized void signal(){ 
     this.counter++; 
     notifyAll(); 
    } 

    public synchronized void down() throws InterruptedException{ 
     while (this.counter <= 0){ 
      wait(); 
     } 
     this.counter--; 
    } 
} 
+0

我不应该使用内置的cyclicBarrier :) – MedoAlmasry

+0

是的,信号也:) :) – MedoAlmasry

+0

当只有一个线程将被释放时,男孩讨厌使用'notifyAll()'。 – Gray

回答

1

我看到您使用的解决方案从The Little Book of Semaphores。本书的一个要点是你可以用信号量作为唯一的协调原语来解决许多协调问题。使用同步的来实现信号量是完全正确的,因为这是正确执行它的必要条件。然而,它忽略了这一点,但是,在解决应该用信号量解决的难题的方法中,使用同步的

而且,我认为它不工作你的情况,你不拿到在this.turnstile.down()死锁?你在一个信号量上阻塞信号量,该信号持有一个独占锁(通过同步)的对象和方法,将允许释放信号量。

如上所述解决问题:您发信号给线程,他们可以通过从返回barrier.down()。你确保你不会过早返回turnstile.down()

旁白:信号灯实现

你的旗语实施看起来是正确的,但您只允许非负的初始值,这至少是不规范的。有没有这样做的动机,我看不到?如果你认为负面的初始值是错误的,为什么不抛出错误而不是默默地做别的事情?

除了:其他的同步原语

注意,Java构造同步.wait().notify()对应Monitor协调原语。使用监视器(或其他协调原语)而不是信号量来解决难题可能是有益的,但我建议将这些努力分开。我尝试使用Haskell's Software Transactional Memory解决一个难题有点乐趣。

题外话:在流动性

你说你已经尝试的事情,这表明你有一些代码,允许您运行的问题的代码。如果您已经包含了该代码,那将会很有帮助,所以我们也可以轻松地运行它。我可能会检查我的虚拟死锁是否真的发生。