# 模組26 死結問題(DeadLock)、執行緒的過時 API(stop()、resume()) ## 死結(DeadLock) ### 定義 程序執行卡住,無法繼續往下執行。 <style> .alert ol { margin:0; } </style> :::info 我自己認為這個定義還不夠完整,再補充一下:<div style="margin-bottom:12px;" title="保持間距用"></div> 1. 對**多執行緒**(利用同步化鎖定)進行並行控制引發的問題。 2. 通常發生在有 **2 個以上的資源**必須共享的情況,且在執行中的執行緒,必須要同時擁有 2 個資源才能執行任務。 <div style="margin-bottom:12px;" title="保持間距用"></div> 舉例:<div style="margin-bottom:12px;" title="保持間距用"></div> > 某一個執行緒取得 A 資源的 Lock,進入 A 資源的 Monitor,在等待 B 資源。但其實另一個執行緒取得了 B 資源,正在等待 A 資源。 ::: ### 原因 多執行緒的同步化鎖定(`synchronized`)原本就可能會造成執行緒間相互等待的死結情況,Java 編譯器無法在編譯時期得知是否會有死結的發生,須由程式設計師自行掌控,再加上多執行緒的行為難以預測,最好的方法是預防而不是偵測它。 ### 預防死結 最簡單的方式是將一群所物件的鎖定動作,按照相同的順序進行處理。 :::warning 解決死結問題,可能會引發其他的問題:活結(LiveLock)、餓死(Starvation)。 ::: ### 哲學家就餐問題(Dining philosophers problem) [對多執行緒進行並行控制的著名問題情境]((https://zh.wikipedia.org/wiki/%E5%93%B2%E5%AD%A6%E5%AE%B6%E5%B0%B1%E9%A4%90%E9%97%AE%E9%A2%98)),不同處理方法可能造成死結、活結的情況。 #### 問題情境: > 哲學家就餐問題可以這樣表述,假設有五位哲學家圍坐在一張圓形餐桌旁,做以下兩件事情之一:吃飯,或者思考。吃東西的時候,他們就停止思考,思考的時候也停止吃東西。餐桌中間有一大碗義大利麵,每位哲學家之間各有一支餐叉。因為用一支餐叉很難吃到義大利麵,所以假設哲學家必須用兩支餐叉吃東西。他們只能使用自己左右手邊的那兩支餐叉。 #### 此問題中的死結情況: > 哲學家在左邊的叉子可用(沒有其他人拿起)之前處於思考狀態。如果左邊的叉子可用,就拿起來。哲學家等待右邊的叉子可用。如果右邊的叉子可用,就拿起來。如果兩個叉子都已經拿起來,開始吃義大利麵,每次吃麵都花費同樣的時間。吃完後先放下左邊的叉子。然後放下右邊的叉子。開始思考。(進入一個循環) 這個解法是失敗的,當每個哲學家都拿起左側的叉子,等待右側的叉子可用時,就會進入死結狀態,每個哲學家將永遠都在等待(右邊的)另一個哲學家放下叉子。 #### 此問題中的活結情況: >如果特定的哲學家由於時間問題而無法同時獲得兩個資源,那麼資源匱乏也可能獨立於死結而發生。例如,假設規定當哲學家等待另一支餐叉超過五分鐘後就放下自己手裡的那一支餐叉,並且再等五分鐘後進行下一次嘗試。這個策略消除了死結(系統總會進入到下一個狀態),但仍然有可能發生「活結」。如果五位哲學家在完全相同的時刻進入餐廳,並同時拿起左邊的餐叉,那麼這些哲學家就會等待五分鐘,同時放下手中的餐叉,再等五分鐘,又同時拿起這些餐叉。 ## Thread 相關的過時 API(Deprecation of APIs) Java 更新會為標準類別函式庫(class library)帶來新的類別、介面及其相關的屬性、方法、建構子,也有可能取代既有的內容。 有些方法因為各種原因已經不建議使用,但仍然擺在類別函式庫中,可以被使用,稱為過時的 API(Deprecation of APIs),在編寫程式碼時如果有使用到,編譯器就會顯示: ``` xxx.java uses or overrides a deprecated API ``` [與執行緒相關的過時 API](/@czyue/BymG51vQu#過時APIs:) 有:`stop()`、`resume()` 等,主要就是因為它們容易造成死結,所以 Java 將其標示為過時(Deprecation)。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up