如何避免死锁
???? 線程A需要資源X,而線程B需要資源Y,而雙方都掌握有對(duì)方所要的資源,這種情況稱為死鎖(deadlock),或死亡擁抱(the deadly embrace)。
在并發(fā)程序設(shè)計(jì)中,死鎖 (deadlock) 是一種十分常見的邏輯錯(cuò)誤。通過采用正確的編程方式,死鎖的發(fā)生不難避免。
死鎖的四個(gè)必要條件
------------------------------
在計(jì)算機(jī)專業(yè)的本科教材中,通常都會(huì)介紹死鎖的四個(gè)必要條件。這四個(gè)條件缺一不可,或者說只要破壞了其中任何一個(gè)條件,死鎖就不可能發(fā)生。我們來復(fù)習(xí)一下,這四個(gè)條件是:
解除死鎖的必要條件
不難看出,在死鎖的四個(gè)必要條件中,第二、三和四項(xiàng)條件比較容易消除。通過引入事務(wù)機(jī)制,往往可以消除第二、三兩項(xiàng)條件,方法是將所有上鎖操作均作為事務(wù)對(duì)待,一旦開始上鎖,即確保全部操作均可回退,同時(shí)通過鎖管理器檢測(cè)死鎖,并剝奪資源(回退事務(wù))。這種做法有時(shí)會(huì)造成較大開銷,而且也需要對(duì)上鎖模式進(jìn)行較多改動(dòng)。
消除第四項(xiàng)條件是比較容易且代價(jià)較低的辦法。具體來說這種方法約定:上鎖的順序必須一致。具體來說,我們?nèi)藶榈亟o鎖指定一種類似“水位”的方向性屬性。無論已持有任何鎖,該執(zhí)行緒所有的上鎖操作,必須按照一致的先后順序從低到高(或從高到低)進(jìn)行,且在一個(gè)系統(tǒng)中,只允許使用一種先后次序。
請(qǐng)注意,放鎖的順序并不會(huì)導(dǎo)致死鎖。也就是說,盡管按照 鎖A, 鎖B, 放A, 放B 這樣的順序來進(jìn)行鎖操作看上去有些怪異,但是只要大家都按先A后B的順序上鎖,便不會(huì)導(dǎo)致死鎖。
解決方法:
1 使用事務(wù)時(shí),盡量縮短事務(wù)的邏輯處理過程,及早提交或回滾事務(wù); (細(xì)化處理邏輯,執(zhí)行一段邏輯后便回滾或者提交,然后再執(zhí)行其它邏輯,直到事物執(zhí)行完畢提交)
2 設(shè)置死鎖超時(shí)參數(shù)為合理范圍,如:3分鐘-10分種;超過時(shí)間,自動(dòng)放棄本次操作,避免進(jìn)程懸掛;
3 優(yōu)化程序,檢查并避免死鎖現(xiàn)象出現(xiàn);
4 .對(duì)所有的腳本和SP都要仔細(xì)測(cè)試,在正是版本之前。
5 所有的SP都要有錯(cuò)誤處理(通過@error)
6 一般不要修改SQL SERVER事務(wù)的默認(rèn)級(jí)別。不推薦強(qiáng)行加鎖
另外參考的解決方法:
按同一順序訪問對(duì)象
??? 如果所有并發(fā)事務(wù)按同一順序訪問對(duì)象,則發(fā)生死鎖的可能性會(huì)降低。例如,如果兩個(gè)并發(fā)事務(wù)獲得 Supplier 表上的鎖,然后獲得 Part 表上的鎖,則在其中一個(gè)事務(wù)完成之前,另一個(gè)事務(wù)被阻塞在 Supplier 表上。第一個(gè)事務(wù)提交或回滾后,第二個(gè)事務(wù)繼續(xù)進(jìn)行。不發(fā)生死鎖。將存儲(chǔ)過程用于所有的數(shù)據(jù)修改可以標(biāo)準(zhǔn)化訪問對(duì)象的順序。
???
??? 避免事務(wù)中的用戶交互
??? 避免編寫包含用戶交互的事務(wù),因?yàn)檫\(yùn)行沒有用戶交互的批處理的速度要遠(yuǎn)遠(yuǎn)快于用戶手動(dòng)響應(yīng)查詢的速度,例如答復(fù)應(yīng)用程序請(qǐng)求參數(shù)的提示。例如,如果事務(wù)正在等待用戶輸入,而用戶去吃午餐了或者甚至回家過周末了,則用戶將此事務(wù)掛起使之不能完成。這樣將降低系統(tǒng)的吞吐量,因?yàn)槭聞?wù)持有的任何鎖只有在事務(wù)提交或回滾時(shí)才會(huì)釋放。即使不出現(xiàn)死鎖的情況,訪問同一資源的其它事務(wù)也會(huì)被阻塞,等待該事務(wù)完成。
???
??? 保持事務(wù)簡(jiǎn)短并在一個(gè)批處理中
??? 在同一數(shù)據(jù)庫中并發(fā)執(zhí)行多個(gè)需要長時(shí)間運(yùn)行的事務(wù)時(shí)通常發(fā)生死鎖。事務(wù)運(yùn)行時(shí)間越長,其持有排它鎖或更新鎖的時(shí)間也就越長,從而堵塞了其它活動(dòng)并可能導(dǎo)致死鎖。保持事務(wù)在一個(gè)批處理中,可以最小化事務(wù)的網(wǎng)絡(luò)通信往返量,減少完成事務(wù)可能的延遲并釋放鎖。
???
??? 使用低隔離級(jí)別
??? 確定事務(wù)是否能在更低的隔離級(jí)別上運(yùn)行。執(zhí)行提交讀允許事務(wù)讀取另一個(gè)事務(wù)已讀取(未修改)的數(shù)據(jù),而不必等待第一個(gè)事務(wù)完成。使用較低的隔離級(jí)別(例如提交讀)而不使用較高的隔離級(jí)別(例如可串行讀)可以縮短持有共享鎖的時(shí)間,從而降低了鎖定爭(zhēng)奪。
???
??? 使用綁定連接
??? 使用綁定連接使同一應(yīng)用程序所打開的兩個(gè)或多個(gè)連接可以相互合作。次級(jí)連接所獲得的任何鎖可以象由主連接獲得的鎖那樣持有,反之亦然,因此不會(huì)相互阻塞。
總結(jié)
- 上一篇: 二叉树(中序遍历)非递归
- 下一篇: DevExpress RichEditC