Udemy Course Multithreading, Concurrency & Performance 21

Deadlock

ZONGRU Li
Sep 2, 2021

通常Multi-Thread程式運行會有互相排隊的狀況就是形成了Deadlock

例如以下兩個Thread進行的邏輯處理:

實際可能的執行順序推敲如下:

A先被Thread1鎖住了

Thread2會一直卡在等著鎖A那一步,直到Thread1內把A解鎖

但是Thread1下一步卻是...

Thread1想要執行的下一個動作lock(B)做不下去

此狀況就是形成了

這就好像兩台汽車行駛在十字路口

A由北向南,B由西向東,中間有個交會處可能會有碰撞(形成Dead Lock)

情況如以下程式範例:

嘗試製作兩個物件鎖roadA與roadB,分別先後執行

同樣也寫一個takeRoadB()

接著製作TrainA物件來驅動intersection內的takeRoadA()

同理再做一個TrainB物件來驅動intersection內的takeRoadB()

最後在Main裡面建立單一個Intersection物件

分別注入給後面建立的TrainA與TrainB的Thread物件

並啟動

實際執行會看到:

注意右上中止鈕亮著,所以卡住了

仔細看看log:

重複跑會看到不同狀況:

像是一開始就撞車:

完整code如下:

以上展示了發生Deadlock的情境

總結如下:

  1. Mutual Exclusion(互斥):在某時間點,僅單一個Thread可以執行(使用道路)
  2. Hold & Wait(停止與等待):至少一個Thread持有resource,並等待另一個resource(如上例,RoadA等待RoadB)
  3. Non-preemptive allocation(非搶佔式分配):resource僅有被該Thread執行完才釋放,而其他Thread只能等待該resource被釋放才能執行
  4. Circular wait:如上例,某Thread把持著RoadA並等待RoadB被釋放,但是另一個Thread反而把持著RoadB並等待RoadA被釋放

而通常要避免Deadlock的狀況,比較常見的方式就是盡力避免Circular wait

比如前面所說的如下狀況:

原本邏輯如下:

其中改變一下邏輯順序:

此狀況就不會造成Deadlock!

回到前面的範例Code,將以下這個地方:

我複製一個叫:Main_deadlock_solu來改

改成:

執行後看到:

所以完整code變成:

結論其他關連技術(找出Deadlock):

  1. Deadlock detection — Watchdog(偵測沒回應的Thread並停止該Thread)
  2. Thread interruption(not possible with synchronized)實際就是多Thread的Watchdog
  3. tryLock operations(not possible with synchronized)另一個Thread在進到會造成lock邏輯前先確認這是否已經被其他Thread 造成lock了

(上面2&3阻止不了synchronized)

參考課程

--

--

ZONGRU Li
ZONGRU Li

Written by ZONGRU Li

2022/11/17 開源部分個人筆記給LINE "Java程式語言討論區"社群,希望能對社群的技術學習做一點點貢獻.(掩面....記得退訂閱!

No responses yet