在并發(fā)程序設(shè)計中,死鎖 (deadlock) 是一種十分常見的邏輯錯誤。通過采用正確的編程方式,死鎖的發(fā)生不難避免。
死鎖的四個必要條件
在計算機(jī)專業(yè)的本科教材中,通常都會介紹死鎖的四個必要條件。這四個條件缺一不可,或者說只要破壞了其中任何一個條件,死鎖就不可能發(fā)生。我們來復(fù)習(xí)一下,這四個條件是:
?互斥(Mutual exclusion):存在這樣一種資源,它在某個時刻只能被分配給一個執(zhí)行緒(也稱為線程)使用;
?持有(Hold and wait):當(dāng)請求的資源已被占用從而導(dǎo)致執(zhí)行緒阻塞時,資源占用者不但無需釋放該資源,而且還可以繼續(xù)請求更多資源;
?不可剝奪(No preemption):執(zhí)行緒獲得到的互斥資源不可被強(qiáng)行剝奪,換句話說,只有資源占用者自己才能釋放資源;
?環(huán)形等待(Circular wait):若干執(zhí)行緒以不同的次序獲取互斥資源,從而形成環(huán)形等待的局面,想象在由多個執(zhí)行緒組成的環(huán)形鏈中,每個執(zhí)行緒都在等待下一個執(zhí)行緒釋放它持有的資源。
解除死鎖的必要條件
不難看出,在死鎖的四個必要條件中,第二、三和四項條件比較容易消除。通過引入事務(wù)機(jī)制,往往可以消除第二、三兩項條件,方法是將所有上鎖操作均作為事務(wù)對待,一旦開始上鎖,即確保全部操作均可回退,同時通過鎖管理器檢測死鎖,并剝奪資源(回退事務(wù))。這種做法有時會造成較大開銷,而且也需要對上鎖模式進(jìn)行較多改動。
消除第四項條件是比較容易且代價較低的辦法。具體來說這種方法約定:上鎖的順序必須一致。具體來說,我們?nèi)藶榈亟o鎖指定一種類似“水位”的方向性屬性。無論已持有任何鎖,該執(zhí)行緒所有的上鎖操作,必須按照一致的先后順序從低到高(或從高到低)進(jìn)行,且在一個系統(tǒng)中,只允許使用一種先后次序。
請注意,放鎖的順序并不會導(dǎo)致死鎖。也就是說,盡管按照 鎖A, 鎖B, 放A, 放B 這樣的順序來進(jìn)行鎖操作看上去有些怪異,但是只要大家都按先A后B的順序上鎖,便不會導(dǎo)致死鎖。
舉例
假如有三個對象A、B、C,我們?nèi)藶榧s定它們的鎖序是: A 先于 B 先于 C。舉例說來,下列鎖序均為合法:
? 鎖C,放C
? 鎖B,放B
? 鎖B,鎖C,放B,放C
? 鎖B,鎖C,放C,放B
? 鎖A,放A
? 鎖A,鎖C,放A,放C
? 鎖A,鎖C,放C,放A
? 鎖A,鎖B,放A,放B
? 鎖A,鎖B,放B,放A
? 鎖A,鎖B,鎖C,放A,放B,放C
? 鎖A,鎖B,鎖C,放C,放B,放A
而在上面定義的系統(tǒng)中,可能導(dǎo)致發(fā)生死鎖典型上鎖序列包括:
? 鎖B,鎖A,鎖C,放C,放A,放B
(因為先B后A的上鎖順序違反了鎖序約定,如果另一執(zhí)行緒同時按照先A后B的順序上鎖,則可能由于執(zhí)行緒甲獲得了B,執(zhí)行緒乙獲得了A,而導(dǎo)致雙方同時等待對方釋放所持有的鎖,從而形成死鎖局面;解法是將操作序列中增加適當(dāng)?shù)逆i操作,即改為鎖B,放B,鎖A,鎖B,鎖C,放C,放A,放B)
或者說,只要拿鎖的時候不出現(xiàn)逆序(例如拿著C的時候試圖抓B或A,或者拿著B的時候試圖抓A),并出現(xiàn)潛在逆序的時候先放掉“小”鎖再抓大的,就一定不造成死鎖了。
1、避免給一個鎖嵌套上鎖,在持有一個鎖的時候,不要再給這個鎖上鎖。
如果使用多個鎖,使用std::lock。2、在持有鎖時,不要調(diào)用別人提供的函數(shù),因為你不清楚別人的代碼怎么實現(xiàn)的,不知道它是不是在使用鎖。
3、給多個鎖上鎖時,固定順序。如果在給多個所上鎖,并且無法使用std::lock,最好的做法就是在每一個線程中,都按照同樣的順序。
4、分層次來使用鎖,把程序分成幾個層次。區(qū)分每個層次中使用的鎖,當(dāng)一個線程已經(jīng)持有更低層次的鎖時,不允許使用高層次的鎖。
可以在程序運(yùn)行時給不同的鎖加上層次號,記錄每個線程持有的鎖。擴(kuò)展資料:解決方法在系統(tǒng)中已經(jīng)出現(xiàn)死鎖后,應(yīng)該及時檢測到死鎖的發(fā)生,并采取適當(dāng)?shù)拇胧﹣斫獬梨i。
死鎖預(yù)防。這是一種較簡單和直觀的事先預(yù)防的方法。
方法是通過設(shè)置某些限制條件,去破壞產(chǎn)生死鎖的四個必要條件中的一個或者幾個,來預(yù)防發(fā)生死鎖。預(yù)防死鎖是一種較易實現(xiàn)的方法,已被廣泛使用。
但是由于所施加的限制條件往往太嚴(yán)格,可能會導(dǎo)致系統(tǒng)資源利用率和系統(tǒng)吞吐量降低。死鎖避免。
系統(tǒng)對進(jìn)程發(fā)出的每一個系統(tǒng)能夠滿足的資源申請進(jìn)行動態(tài)檢查,并根據(jù)檢查結(jié)果決定是否分配資源;如果分配后系統(tǒng)可能發(fā)生死鎖,則不予分配,否則予以分配。這是一種保證系統(tǒng)不進(jìn)入死鎖狀態(tài)的動態(tài)策略。
死鎖檢測和解除。先檢測:這種方法并不須事先采取任何限制性措施,也不必檢查系統(tǒng)是否已經(jīng)進(jìn)入不安全區(qū),此方法允許系統(tǒng)在運(yùn)行過程中發(fā)生死鎖。
但可通過系統(tǒng)所設(shè)置的檢測機(jī)構(gòu),及時地檢測出死鎖的發(fā)生,并精確地確定與死鎖有關(guān)的進(jìn)程和資源。檢測方法包括定時檢測、效率低時檢測、進(jìn)程等待時檢測等。
然后解除死鎖:采取適當(dāng)措施,從系統(tǒng)中將已發(fā)生的死鎖清除掉。這是與檢測死鎖相配套的一種措施。
當(dāng)檢測到系統(tǒng)中已發(fā)生死鎖時,須將進(jìn)程從死鎖狀態(tài)中解脫出來。常用的實施方法是撤銷或掛起一些進(jìn)程,以便回收一些資源,再將這些資源分配給已處于阻塞狀態(tài)的進(jìn)程,使之轉(zhuǎn)為就緒狀態(tài),以繼續(xù)運(yùn)行。
死鎖的檢測和解除措施,有可能使系統(tǒng)獲得較好的資源利用率和吞吐量,但在實現(xiàn)上難度也最大。參考資料:死鎖百度百科。
破壞互斥條件
破壞互斥條件即允許多個進(jìn)程同時訪問資源。由于多數(shù)資源的必須互斥訪問這一固有特性不能改變,因此,死鎖的預(yù)防通過破壞這個必要條件實現(xiàn)在很多場合是行不通的。例如,打印機(jī)資源必須互斥使用,否則幾個進(jìn)程同時使用,每個進(jìn)程各打印一行,這種輸出信息的方式顯然是不能被用戶接受的。
破壞占有和等待條件
采用資源靜態(tài)分配法可破壞這一條件,該方法是指在進(jìn)程運(yùn)行前,一次性地_請分配它運(yùn)行所需的全部資源。若系統(tǒng)有足夠的資源分配給某一進(jìn)程,則一次性地將其所需資源分配給該進(jìn)程,這樣,在進(jìn)程運(yùn)行期間便不會再提出任何資源請求,從而使等待條件不成立。如果分配時有一種資源要求不能滿足,則進(jìn)程需要的其他資源也先不分配給進(jìn)程,從而避免進(jìn)程在等待期間占用任何資源,破壞了占用條件,從而避免死鎖的發(fā)生。
該方法控制簡單且容易實現(xiàn),但由于進(jìn)程運(yùn)行期間對所需資源的全部占用,使得某些使用時間很短的資源被長時間占用,這樣會嚴(yán)重影響系統(tǒng)資源的充分利用,導(dǎo)致資源利用率降低,同吋也影響到未獲得全部資源的進(jìn)程推遲運(yùn)行。
破壞不剝奪條件
采用剝奪式控制方法可以破壞該條件,該方法是使一個已保持了某些資源的進(jìn)程,由于新的資源要求目前得不到滿足,它必須先暫時釋放巳保持的所有資源(一種剝奪式),然后去等待,以后再一起向系統(tǒng)提出巾請,這樣也能防止死鎖。這種方法實現(xiàn)起來相對W難,為了保護(hù)進(jìn)程自動放棄資源的現(xiàn)場以及后來的再次恢復(fù),需要付出高昂的代價,并且這種方法只適用于處理機(jī)和存儲器資源,對其他資源,此法不宜使用。
破壞循環(huán)等待條件
采用資源順序分配法可破壞該條件。這種分配方法的基本思想是:把系統(tǒng)的全部資源分成多個層次,一個進(jìn)程得到某一層的一個資源后,它只能再_請較高一層的資源;當(dāng)一個進(jìn)程要釋放某層的一個資源時,必須先釋放所占有的較高層的資源;當(dāng)一個進(jìn)程獲得了某一層的一個資源后,它想再申請該層中的另一個資源,就必須先釋放在該層中巳占有的資源?;蛘哒f,進(jìn)程釋放資源的順序是按照中請資源的相反順序進(jìn)行的。這樣可以預(yù)防循環(huán)等待現(xiàn)象的發(fā)生,因此不會發(fā)生死鎖。使用該方法要特別注意的問題是對資源所處層次的安排。在通常情況下,把各進(jìn)程經(jīng)常用到的、比較普遍的資源安排在較低的層次上,把重要且相對匱乏的資源安排在較高的層次上,以便實現(xiàn)對各資源的最大限度的利用。該方法相對于前面介紹的方法,在資源利用率和系統(tǒng)吞吐量上都有明顯的改善。但也存在一些缺陷。
(1)低層次的資源必須在進(jìn)程請求分配髙層次的資源之前提前申請,這對于暫時不需使用的低層次資源來說,會因空閑等待而產(chǎn)生浪費(fèi)。
(2)各類設(shè)備的資源層次一經(jīng)設(shè)定,便不能經(jīng)常隨意改動,這就限制了新類型設(shè)備的增加。
(3)各資源的層次是按照大多數(shù)進(jìn)程使用資源的順序設(shè)置的。對于資源使用與此層次相閃配的進(jìn)程,資源能得到有效的利用,否則,資源的浪費(fèi)現(xiàn)象將仍然存在。
聲明:本網(wǎng)站尊重并保護(hù)知識產(chǎn)權(quán),根據(jù)《信息網(wǎng)絡(luò)傳播權(quán)保護(hù)條例》,如果我們轉(zhuǎn)載的作品侵犯了您的權(quán)利,請在一個月內(nèi)通知我們,我們會及時刪除。
蜀ICP備2020033479號-4 Copyright ? 2016 學(xué)習(xí)鳥. 頁面生成時間:3.071秒