同步、異步、阻塞、非阻塞概念
同步和異步
結果的通知機制。自己問還是別人通知。
同步:主動等待結果的返回。如阻塞等待,輪詢(同步非阻塞)。
異步:被動等待結果的返回。如 消息回調。
阻塞和非阻塞
結果返回以前,調用方的狀態。等還是不等。
阻塞:結果返回以前,什麼也不幹。
非阻塞:在結果返回以前,可以先做一些其他事情。
Monitor鎖
下面所說的獲取monitor鎖都是指的先使用synchronized獲取對象鎖
不應該叫synchronized(mutex)爲鎖,而應該是某個線程獲取了與mutex關聯的monitor鎖。
wait 與 notify
wait 理解成線程在等待直到該對象可用。(被notify後就不再等待)
notify理解成線程通知該對象可用。
使用wait的注意事項
-
wait必須在同步方法中使用,因爲wait必須由擁有monitor(已用synchronize獲取鎖)的線程調用。
-
wait可以被中斷,爲了防止wait被interrupt喚醒,wait方法需要在循環中使用。
-
使用wait後自動釋放線程對應的鎖。–release ownership of this monitor
-
wait會等待直到其他線程調用notify/notifyAll喚醒。–waits until anthoer thread notifies threads waiting on this object’s monitor to wake up…
-
被notify/notifyAll喚醒後會重新獲得鎖的擁有權,然後接着執行。–re-obtain ownership of the monitor and resumes execution.
-
線程調用wait後, 會加入與之對應的wait set.每個對象都有一個與之對應的wait set.使用notify會將其中一個彈出,notifyAll彈出所有線程。(C5.3.2)
Causes the current thread to wait until another thread invokes the
* {@link java.lang.Object#notify()} method or the
* {@link java.lang.Object#notifyAll()} method for this object.
* In other words, this method behaves exactly as if it simply
* performs the call {@code wait(0)}.
*
* The current thread must own this object’s monitor. The thread
* releases ownership of this monitor and waits until another thread
* notifies threads waiting on this object’s monitor to wake up
* either through a call to the {@code notify} method or the
* {@code notifyAll} method. The thread then waits until it can
* re-obtain ownership of the monitor and resumes execution.
* As in the one argument version, interrupts and spurious wakeups are
* possible, and this method should always be used in a loop:
* synchronized (obj) {
* while (<condition does not hold>)
* obj.wait();
* … // Perform action appropriate to condition
* }
* This method should only be called by a thread that is the owner
* of this object’s monitor. See the {@code notify} method for a
* description of the ways in which a thread can become the owner of a monitor.
使用notify的注意
-
必須在同步方法中使用wait、notify,因爲他們的使用前提都是持有monitor所有權。
-
同步代碼塊的monitor必須與執行 wait 、notify的對象一致,也就是說對哪個對象同步,才能調用那個對象的 wait、notify。
例子:
若不是用的notifyAll, 則不能用於多線程環境
在while而不是if中調用wait!否則一旦被interrupt,會跳過判斷繼續執行。如
測試主動interrupt對if中使用wait的影響
這裏主動interrupt,可見當producer被interrupt後,producer就略過了判斷,繼續添加了一個event
wait與sleep的
- 相同:
使線程阻塞
可以中斷 - 不同:
wait是Object的方法,sleep是Thread的
wait必須要在同步代碼塊中執行。
wait會釋放monitor的鎖,sleep不會
sleep短暫休眠後會退出阻塞?(TODO)wait(沒有指定時間的話)必須被中斷纔會退出阻塞。
synchronized的缺點
-
無法中斷
synchronized不像sleep和wait那樣,可以被中斷。 -
沒有等待時間
其他線程獲取鎖的擁有權必須要等待鎖的擁有者(線程)釋放後才能執行。
利用wait、notify實現可中斷的BooleanLock
p96-104
一旦從wait中被喚醒則有機會檢查lock是否爲false,爲false則修改獲取鎖的線程cureentLockThread爲自己,並設置lock爲true.防止其他線程繼續爭搶。
如果wait超時會報錯,notify後超時 也主動拋錯。
關鍵代碼
從wait中被notify或者等待超時後,會因爲while(locked),locked爲false,說明沒有線程持有monitor的擁有權,因此跳出while設置locked=true;this.currentThread=currentThread();
優化,超時後清除blackList
發佈於2019年7月7日 16:40:43