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

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

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