Udemy Course Multithreading, Concurrency & Performance 28
過去章節有介紹過一些Inter-thread:
- Thread.interrupt(),A Thread可以中斷B Thread
- Thread.join(),在A Thread內做BThread.join(),A會等B做完才繼續
- Semaphore在不同Thread間acquire()與release()
接著介紹另個一般Inter-thread communication=>Condition variables
(java.util.concurrent.locks.Condition)
狀況情境如下:
比如A Thread先執行確認條件
接著B Thread執行
再接著A Thread拿到訊號後,可以再次重新確認Condition
Condition Variable都會搭配lock使用,以確保”Check “是atomic!
實際Code與可能情境寫法如下(配合Reentrant lock)
考量到一個簡單的帳號密碼檢核
通常User在前端UI介面上敲定帳號與密碼後
送到後端系統,我們會實際把帳密拿去DB比對
但是拿去跟DB內資料比對這件事是貴的
所以至少後端系統至少確定過來的帳號與密碼不是null後才去跟DB資料比對
初步寫法如下:
上圖當某Thread進去while迴圈檢核到當前的帳號或密碼有null時
會停止在condition.await() =>等待別的Thread發送signal再次while檢核
並且執行await()的Sleep前,背後連帶會執行lock.unlock()
此時UI Thread如下右邊執行
上圖UI Thread進到lock.lock()內
在拿到User輸入的帳號密碼後會走到condition.signal()發送訊號
但是有個重點是這個condition.signal()只會給單一個在await()的Thread訊號
只有ONLY ONE會收到訊號(i.e.多個都在await()的Threads只有一個會拿到)
接著
其中有個問題在finally又做了unlock()
也就是在做doStuff()前又做了unlock,講師回應如下
結論:
Condition.await(),與其他型式的await()
- void await() — unlock lock(所以另一個UI Thread才能鎖住Resource物件的帳號密碼)並Sleep,wait until signaled
- long awaitNanos(long NanosTimeout) — wait no longer than nanosTimeout
- boolean await(long time,TimeUnit unit) — wait no longer than time,in given time units
- boolean awaitUntil(Data deadline) — wake up before deadline date
Condition.signal()
- void signal() — 喚醒正在等待condition variable的"一個"Thread
- 一個單一Thread要被喚醒,需要拿到condition variable相關的lock
- 若當下沒有Thread在等待condition variable,則signal()發動不做任何事!
Condition.signalAll()
- 直接廣播一個signal()給所有Thread,尤其是正在等待condition variable的
- 執行signalAll()的Thread不用瞭解當下多少個Thread卡在await(),甚至不需要知曉有多少Thread存在,跑了就對了!(另一個跟Semaphore差異,Semaphore做release還要一個個去執行)
後記,事後對await()背後動作研究了一下,確定的動作是
當左邊Thread進到await()
- await()內會先執行lock.unlock() -->右邊Thread才能進得去lock.lock()
- 接著右邊發動signal導致左邊Thread甦醒等待離開await(),但需要取回lock
- 右邊Thread跑完signal()後走到finally區塊的lock.unlock()
- 左邊Thread才真的可以離開await()
(但是只知道左邊Thread這時要拿著lock,看邏輯來說應該有做lock.lock())
5. 接著左邊Thread進到下一輪while判斷式,若因為不符合,不在進到await()
6.所以左邊Thread最終走到finally區塊的lock.unlock() ←邏輯上這是await()鎖上的
看到原生Java doc只提到await()甦醒後要拿到鎖
await()甦醒後到底有沒重作lock.lock()不確定
以下這課程影片都學生提問,講師給的範例code,供研究await()行為
最後發現我要的解答在底下留言問題中: