2014-09-27 89 views
-2

我在網上搜索一個生產者消費者問題和我有this link上同步的需要。 程序員使用矢量這裏的sharedqueue什麼是線程安全的對象

我想爲什麼我需要一個同步塊作爲向量已經線程安全。它必須自己處理線程。

但是當我試圖通過移除synchronized塊做到這一點。它給了我一個IllegalMonitorStateException。以下是代碼片段生產方法

private void produce(int i) throws InterruptedException { 

    //wait if queue is full 
    while (sharedQueue.size() == SIZE) { 
     // synchronized (sharedQueue) { 
      System.out.println("Queue is full " + Thread.currentThread().getName() 
           + " is waiting , size: " + sharedQueue.size()); 

      sharedQueue.wait(); 
     // } 
    } 

    //producing element and notify consumers 
    // synchronized (sharedQueue) { 
     sharedQueue.add(i); 
     sharedQueue.notifyAll(); 
    // } 
} 

我的問題是,爲什麼我們需要一個已經線程對象上同步或採取鎖?

+0

閱讀wait()和notify()的文檔:它清楚地表明您需要有鎖才能調用這些方法。 – 2014-09-27 14:39:21

回答

2

Wihtout同步,你可以有這樣的:

Producer Thread    Consumer Thread     
          if (sharedQueue.isEmpty) { 
sharedQueue.add(i); 
sharedQueue.notifyAll(); 
            sharedQueue.wait() 
          } 

所以,儘管有數據在隊列中,消費者線程將等待可能永遠,因爲它之間添加的東西得到的測試數據,並開始等待有關添加數據的通知。

當然,還有一些解決方法,比如wait上的超時,但是這些都有輪詢開銷,由於輪詢間隔引起的延遲,難看的代碼等等。當你可以使用同步時,沒有理由訴諸此類事情。


那麼,爲什麼它是不夠的,隊列類是線程安全的?那麼,線程安全的課程並不神奇!線程安全意味着,對該類實例的單個方法調用是線程安全的。因此,例如,如果兩個線程在同一時間,以同一實例做add,它不會破壞任何東西,消除與其他或類似的東西一個操作。

但是,如果你有多個線程執行多個操作,那麼他們可以交錯,這是許多線程和搶先式多任務畢竟整點!那麼交錯操作會發生什麼,這取決於操作。例如,只有add的許多線程會以某種未指定的順序添加內容,但這可能是正確的。但是,如果您不希望操作以「隨機」順序發生,則需要使用同步。

如上例所示,在這種情況下,「隨機」順序可能導致消費者無限期地等待隊列中的數據。事實上,如果你有序列「做修改,通知服務員」,服務員在做「看看有什麼需要做,否則等待」,你有同樣的問題,並且必須同時使用修改通知和檢查等待。


,你會得到錯誤,因爲Java要求你通知的時候,因爲上面解釋的,它使無鎖沒有意義的有鎖,這將永遠是一個錯誤,一個錯誤。這是不是Java具體,這是這類機制的根本,他們總是需要的鎖,在這個Wikipedia article section閱讀更多。

+0

我知道我可以調整代碼和所有,但我想知道爲什麼我們需要鎖定一個線程安全的對象?正如你的編輯所說。 **通知/等待沒有鎖定沒有意義,**共享隊列是一個線程安全的對象。內部必須已經有一個鎖定 – gusainhimanshu 2014-09-27 14:52:11

+0

增加了一些關於爲什麼有一個線程安全的容器在這裏沒有幫助的文字。 – hyde 2014-09-27 15:06:01

+0

感謝hyde的解釋。謝謝海德 – gusainhimanshu 2014-09-28 20:44:00

相關問題