在平常開發,咱們都知道wait/notify有着很是固定的一套模板,就是下面的樣子,synchronized同步塊包裹着Object.wait()
方法,若是不經過同步塊包住的話JVM會拋出IllegalMonitorStateException
異常。java
synchronized(lock) { while(!condition){ lock.wait(); } }
那麼爲何要限制這麼寫呢?多線程
假設咱們本身實現了一個BlockingQueue的代碼。
若是Object.wait()/notify不須要同步,那麼咱們的代碼會形以下面這樣。spa
class BlockingQueue { Queue<String> buffer = new LinkedList<String>(); public void give(String data) { buffer.add(data); notify(); // 往隊列裏添加的時候notify,由於可能有人在等着take } public String take() throws InterruptedException { while (buffer.isEmpty()) // 用while,防止spurious wakeups(虛假喚醒) wait(); // 當buffer是空的時候就等着別人give return buffer.remove(); } }
若是上面的代碼能夠執行的話,多線程狀況下會出現一種狀況:線程
由於你只要用notify,那就是爲了在多線程環境下同步,notify/wait機制自己就是爲了多線程的同步而存在的,那就只能配套synchronized,因此爲了防止上面狀況的發生,就直接強制拋異常來限制開發的代碼模式了。code
試想一種場景,若是沒有wait/notify的掛起喚醒機制,該如何實現BlockingQueueblog
class BlockingQueue { Queue<String> buffer = new LinkedList<String>(); public void give(String data) { buffer.add(data); } public String take() throws InterruptedException { while(buffer.isEmpty) { sleep(10); } return buffer.remove(); } }
若是沒有wait/notify,那麼在take的時候只能經過while循環不停輪詢判斷buffer是否爲空來實時獲取buffer的最新狀態,那麼勢必會形成兩種狀況:隊列
綜上,針對於BlockingQueue這樣的場景,同步塊 + wait/notify 或者 lock + signal/await 就是標配開發