2012-03-07 32 views
3

我正試圖在Java中使用監視器概念實現信號量。即Java類實現弱計數信號量(使用方法初始化,信號和等待)使用監視器概念實現信號量

有人能告訴我,如果這個類是正確的(如果不是有什麼問題):

class MyMonitor 
{ 
    int counter = 0; 

    //init 
    public MyMonitor(int init) 
    { 
     counter = init; 
    } 

    //Signal 
    public synchronized void S() 
    { 
     counter++; 
     notify(); 
    } 

    //Wait 
    public synchronized void W() 
    { 
     if(counter == 0) 
     { 
      try 
      { 
       wait(); 
      } 
      catch(InterruptedException e) { } 
     } 

     counter--; 
    } 
} 

如果這是正確的,有人可以給我一個關於如何測試課程的想法。

回答

0

嗯,我看到的唯一問題是這一部分:

if(counter == 0) 
    { 
     try 
     { 
      wait(); 
     } 
     catch(InterruptedException e) { } 
    } 

    counter--; 

如果線程被中斷,而等待,它只會退出if聲明,遞減到低於0櫃檯,然後你的信號系統去可怕錯誤,因爲現在沒有人會因爲counter小於0而被迫等待。

您應該用while替換if以防萬一。

+1

其他r用「while」表示「真正的弱點」。 – zch 2012-03-07 21:48:45

+0

@zch:好點。 – Tudor 2012-03-07 21:51:08

1

它應該是這樣的(與while,不if):

class YourMonitor 
{ 
    int counter = 0; 

    //init 
    public MyMonitor(int init) 
    { 
     counter = init; 
    } 

    //Signal 
    public synchronized void S() 
    { 
     counter++; 
     notifyAll(); 
    } 

    //Wait 
    public synchronized void W() throws InterruptedException 
    { 
     while (counter <= 0) 
     { 
      wait(); 
     } 

     counter--; 
    } 
} 

如何測試:

public class TestYourSemaphore 
{ 
    private static final int CNT = 100000; 

    private int x = 0; 
    private YourSemaphore s = new YourSemaphore(); 

    public void run() throws InterruptedException 
    { 
     Thread t1 = new Thread(new MyRunnable()); 
     Thread t2 = new Thread(new MyRunnable()); 
     Thread t2 = new Thread(new MyRunnable()); 

     t1.start(); 
     t2.start(); 
     t3.start(); 

     t1.join(); 
     t2.join(); 
     t3.join(); 


     // Verify, that the X has correct value 
     if (x != 3 * CNT) 
     { 
      throw new RuntimeException("Race condition error!"); 
     } 
     System.out.println("Finished"); 
    } 

    private class MyRunnable implements Runnable 
    { 
     @Override 
     public void run() 
     { 
      for (int i = 0; i < CNT; i++) 
      { 
       //un-comment to use Semaphores 
       //s.enter(); 
       x = x + 1; 
       //s.leave(); 
      } 
     } 
    } 
} 
  • 沒有信號,拋出異常的所有時間(幾乎) 。
  • 對於建議的信號量,不會拋出異常。
  • 隨着你的信號量,異常有時會被拋出(但沒有信號燈那麼頻繁)。

與信號燈的問題是:

  1. 線程1具有鎖定
  2. 線程2和線程3是wait()荷蘭國際集團
  3. 線程1調用notifyAll()
  4. 線2和3同時進入臨界區,這是不好的:)
+0

我不明白,爲什麼你用notifyAll()替換notify()。如果沒有notifyAll(),你不會遇到問題,你描述了,因爲你醒來的時候只有一個線程。即使你考慮在另一個評論中描述的虛假喚醒,我也沒有看到notifyAll()的理由 – 2015-02-09 20:34:43