嵌入式軟件設計中查找缺陷的幾個技巧
三、死鎖
在共享資源的系統(tǒng)中,防止訪問沖突極為重要,但這有可能導致另一個問題:死鎖。當通過鎖定一個資源來防止任何其它線程訪問這個資源,以避免競爭條件時,必須對設計進行評估,確保絕對不會發(fā)生死鎖。死鎖測試通常沒有什么效果,因為只有某種特定順序的資源鎖定才可能產生死鎖,而一般的測試不大可能導致這種順序。
死鎖只不過是多線程環(huán)境中一個鎖定資源的問題。以下四個條件必須同時具備,才會發(fā)生死鎖。防止其中任何一個條件出現都可以排除死鎖的可能性:
* 相互排除---每次只有一個線程可以使用某個鎖定的資源;
* 非先占---其它線程不能強迫另一個線程釋放資源;
* 保持并等待---線程在等待需要的其它任何資源時,保持它們已經鎖定的資源;
* 循環(huán)等待---存在一個線程循環(huán)鏈,其中每個線程保持鏈中下一個線程所需要的資源。

圖1:循環(huán)等待
圖1中的資源分配圖是死鎖問題的一個例子。線程1首先鎖定Buf資源,在保持Buf時,指向Bus,然后是Mux。如果線程1一直運行到結束,它最終將釋放所有這些資源。線程2運行時,必須指向Bus、Sem,最后是Mux。線程3運行時,需要Sem和Buf。
在這個設計實例中,無法保證任何一個線程能夠在另一個線程開始執(zhí)行之前結束。如果一個線程不能得到需要的某個資源,它將掛起執(zhí)行(阻塞),直到該資源有效為止。在系統(tǒng)運行過程中,各線程都將對資源進行鎖定或解鎖。由于各線程運行和指向其資源的相對時序各不相同,有可能出現由于各個線程正在等待被其它線程保持的資源,導致所有線程都無法運行的情況。例如,如果線程1保持Buf,線程2保持Bus,而線程3已經取得了Sem,則系統(tǒng)將發(fā)生死鎖。因為按照從Buf到Bus到Sem,再回到Buf的線程分配箭頭,循環(huán)等待條件得到了滿足。

圖2:沒有死鎖
潛在死鎖問題識別出來之后,通常很容易進行修復。在圖2中,對線程3進行了修改,使其在得到Sem之前首先設法指向Buf。這樣,循環(huán)等待的條件就被打破了,系統(tǒng)將不會再受到死鎖的影響。
評論