來源:操作系統死鎖的檢測部分,學到一個死鎖檢測算法,模型基於鄰接矩陣,檢測有向圖是否存在環路。
前提描述:n個進程,用鄰接矩陣描述他們之間的依賴關系,如果R1需要R2先釋放資源,那么在矩陣中記為1。對於一個3個進程的情況,如下圖所示:

R0、R1、R2之間相互等待於是構成了死鎖,在圖中的效應就是構成了環路,我們要通過矩陣的運算,證明某個矩陣是否存在環路。
算法模型:for k:=1 to n do:
for i:=1 to n do:
for j:=1 to n do:
b[i][j]:=b[i][j]V(b[i][k]Λb[k][j]); //V相當於“或”運算,Λ相當於“與”運算。
我的理解、分析:i、j是對矩陣兩個坐標的描述,k是什么呢?我理解的是”橋“,Ri通過Rk能到達Rj,則標記b[i][j]為1。我將從公式和程序驗證的角度進行說明:
程序的驗證,選用C語言進行模擬(ps:我的循環起點是零,但不影響結果,以下的分析都是以0為起點)
1 #include <stdio.h> 2 #define mapsize 3 3 int b[mapsize][mapsize] = { {0,1,0},{0,0,1},{1,0,0} }; 4 void mapout() { 5 int i, j; 6 for (i = 0; i < mapsize; i++) { 7 for (j = 0; j < mapsize; j++) { 8 printf("%d ", b[i][j]); 9 } 10 printf("\n"); 11 } 12 } 13 int main() { 14 int k, i, j, n; 15 n = mapsize; 16 for (k = 0; k < n; k++) { 17 for (i = 0; i < n; i++) { 18 for (j = 0; j < n; j++) { 19 20 printf("b[%d][%d]=b[%d][%d]||(b[%d][%d]&&b[%d][%d])=", i, j, i, j, i, k, k, j); 21 b[i][j] = b[i][j] || (b[i][k] && b[k][j]); 22 printf("%d\n",b[i][j]); 23 24 } 25 } 26 printf("--------------------------------\n"); 27 mapout(); 28 } 29 return 0; 30 }
當k=0時,矩陣運算后的結果如下圖,“橋”,R2通過R0到達R1,標記b[2][1]=1。

當k=1時,矩陣運算后結果如下圖,“橋”,R0通過R1能到達R2,標記b[0][2]=1;R2通過R0、R1能到達R2,標記b[2][2]=1。(列舉到這里,相信你已經有所體會,所以我偷懶少寫點)

運算的最終結果b[i][j]代表Ri能到達Rj,根據回路的定義“V0=Vk的通路”(V0起點,Vk終點),所以死鎖存在判斷的依據是,結果矩陣中是否存在b[i][i]=1(在死鎖判斷中,b[i][j]=b[j][i]也具有說服力,可以說明死鎖特征的相互等待情況)。
公式驗證,簡單說一下,R0到R2,要么R0直連R2,要么R0->R1->R2,用數學語言描述為:b[0][2]=1或者(b[0][1]=1且b[1][2]=1),結合0、1運算特性,公式:b[i][j] = b[i][j] || (b[i][k] && b[k][j]);
k在這里就是1,是個“橋”。(如果老師問你,你回答k是“橋”,然后GG了,本人不負責任)
環路檢測的話,多是使用的深度遍歷、廣度遍歷的搜索方法。兩種方法的時間復雜度是O(n^2),顯然優於三層循環方法。 (寫到這里,似乎上學期算法課,當時的老師沒講清楚,我分析過一波K!!!刪博警告)
