2013-04-01 50 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解決一個難題有點樂趣。

題外話:在流動性

你說你已經嘗試的事情,這表明你有一些代碼,允許您運行的問題的代碼。如果您已經包含了該代碼,那將會很有幫助,所以我們也可以輕鬆地運行它。我可能會檢查我的虛擬死鎖是否真的發生。