爲何wait和notify只能在synchronized中?

前言

wait和notify必須在synchronized塊中,不然會拋出IllegalMonitorStateException。線程

緣由

代碼示例

class BlockingQueue {
    Queue<String> buffer = new LinkedList<String>();

    public void give(String data) {
        buffer.add(data);
        notify();                   
    }

    public String take() throws InterruptedException {
        while (buffer.isEmpty())    
            wait();
        return buffer.remove();
    }
}

代碼示例的問題所在

一個消費者調用take,發現buffer.isEmpty。
在消費者調用wait以前,因爲cpu的調度,消費者線程被掛起,生產者調用give,而後notify。
而後消費者調用wait (注意,因爲錯誤的條件判斷,致使wait調用在notify以後,這是關鍵)。
若是很不幸的話,生產者產生了一條消息後就再也不生產消息了,那麼消費者就會一直掛起,沒法消費,形成死鎖。code

關鍵

老是讓give/notify和take/wait爲原子操做。wait/notify是線程之間的通訊,他們存在競態,咱們必須保證在知足條件的狀況下才進行wait。換句話說,若是不加鎖的話,那麼wait被調用的時候可能wait的條件已經不知足了(如上述)。因爲錯誤的條件下進行了wait,那麼就有可能永遠不會被notify到,因此咱們須要強制wait/notify在synchronized中。rem

相關文章
相關標籤/搜索