2015-05-11 45 views
0

我很好奇,如果有方法來通知正在等待特定鎖定的線程。我收到異常,據我所知這是因爲我用不同的方法在同步的一段代碼內調用notifyAll()。 據我所知,notifyAll()喚醒所有等待所有鎖的線程。下面是一個代碼是否有可能在等待Java中特定鎖的線程上調用notifyAll()?

public class Buffer { 

    private static Buffer instance = null; 
    private boolean full = false; 
    private boolean empty = true; 

    private Object lock1 = new Object(); 
    private Object lock2 = new Object(); 

    private char[] arr; 
    private int i; 

    private Buffer(){ 
     arr = new char[26]; 
     i = 0; 
    } 

    public static synchronized Buffer getInstance(){ 
     if(instance == null){ 
      instance = new Buffer(); 
     } 
     return instance; 
    } 

    public void put(char c){ 

     synchronized(lock1){ 
      while(full){ 
       try{ 
        wait(); 
       }catch(Exception e){} 
      } 

      arr[i++] = c; 
      empty = false; 
      if(i == 25){ 
       full = true; 
       notifyAll(); 
      }else{ 
       full = false; 
      } 
     } 
    } 

    public char get(){ 
     synchronized(lock2){ 
      while(empty){ 
       try{ 
        wait(); 
       }catch(Exception e){} 
      } 

      if(--i == 0){ 
       empty = true; 
      }else{ 
       notifyAll(); 
      } 
      full = false; 
      return arr[i]; 
     } 
    } 

    public boolean isEmpty(){ 
     return i == 0; 
    } 
} 

例外,我得到

java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at Producer_consumer.Buffer.get(Buffer.java:58) 
    at Producer_consumer.Consumer.run(Consumer.java:14) 
    at java.lang.Thread.run(Thread.java:745) 

或者如果它是不可能的..環境下如何這樣都解決了?

+0

等待一個持有的鎖是你應該儘量不要做的事情。帶回調的生產者 - 消費者隊列可以提供幫助。換句話說,wait-and-notify習語就像併發彙編語言。您應該使用java.util.concurrent中的高級併發API。 – scottb

+0

@scottb你意識到['wait'釋放了鎖](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait()),對吧?只有當你調用'wait'的鎖時,你必須持有它,否則會拋出'IllegalMonitortateException'。 –

+0

我現在要做,感謝您的澄清。 – scottb

回答

1

notifyAll喚醒正在等待上一個特定的鎖(即你在呼喚notifyAll一個所有線程,但調用waitnotify/notifyAll您需持顯示器。

同步鎖

如果沒有,當你調用waitnotify在監視器上保持同步鎖,那麼你得到的IllegalMonitorStateException

所以,當你的榜樣,你是內synchronized(lock1){...},則需要到c全部爲lock1.wait()lock1.notifyAll(),同樣在lock2

你現在在做的是在代碼中調用waitthis對象。 Java中的每個對象都有一個監視器,您可以同步,等待並通知它。所以你需要非常小心你執行這些操作的對象。

如果您想通知不同的顯示器,您需要先對其進行同步。

+0

我按照你說的添加了..但是現在消費者線程不起作用,就像我沒有得到任何異常,但是我的消費者線程也沒有做任何事情...... – YohanRoth

+0

您可能會通知錯誤的顯示器。通過你的代碼閱讀,你可能是。您可能想要在put方法中通知lock2,並在get方法中鎖定lock1。爲了做到這一點,你需要同步它:'synchronized(lock2){lock2.notifyAll(); }'在你的put方法中,同樣對於get方法中的lock1。 –

+0

好吧..我照你說的... synchronized(lock1){lock1.wait(); lock1.notifyAll(); } for put and for lock2 for get ... 不適用於消費者... – YohanRoth

0

我很好奇是否有辦法通知正在等待特定鎖的線程。

是。

據我所知,notifyAll()喚醒所有等待所有鎖的線程。

不會。它會喚醒等待您調用對象的所有線程。

它確實是你想要的。

0

根據你的邏輯,lock2被消費者 使用,lock1被生產者使用。

當消費者獲得陣列中的最後一個字符時,將 設置爲true並且完全爲false,誰將通知 生產者線程喚醒並再次開始生產。

所以生產者將保持在等待狀態....

0

朝着解決您的問題,另一種方法是...更改對象上,您需要輸入鎖 。 根據你的程序,我的分析告訴我,你想鎖定的是Buffer 實例。 原因是這個實例包含生產者和消費者都作用於的 字符數組。

所以試試這個結構.....同步(實例)

相關問題