Win32多執行緒之死鎖(DeadLock)
為每一個連結串列(linked list)準備一個critical section之後(關於連結串列,請參看”“,我卻開始了另一個問題。請看下面這個用來交換兩個連結串列內容的函式:
void SwapLists(List *listA, List * listB)
{
List *tmp_list;
EnterCriticalSection(listA->critical_sec);
EnterCriticalSection(listB->critical_sec);
tmp->list = listA->head;
listA->head = listB->head;
listB->head = temp->list;
LeaveCriticalSection(listA->critical_sec);
LeaveCriticalSection(listB->critical_sec);
}
看出問題了嗎?假設下面兩次呼叫發生在不同執行緒的同一個時間點,
執行緒A SwapLists(home_address_list, work_address_list);
執行緒B SwapLists(work_address_list, home_address_list);
而線上程A的SwapLists()的第一次EnterCriticalSection()之後,發生了上下文切換(也就是排程程式選換了一個執行緒),然後執行緒B執行了它的SwapLists()操作,兩個執行緒於是會落入”我等你,你等我“的輪迴,執行緒A需要work_address_list,執行緒B需要home_address_list,而雙方都掌握有對方所要的東西。這種情況成為死鎖(deadlock),或成為死亡擁抱(The Deadlly Embrace)。
任何時候當一段程式碼需要兩個貨更多資源時,都有潛在性的死鎖陰影。死鎖的情況可能非常複雜,許多執行緒的獨立性彼此糾纏在一起,雖然有一些演算法可以偵測並仲裁死鎖狀態,基本上它們仍過於複雜。對大部分程式而言,最好的政策就是找出一種方法以確保死鎖不會發生。稍後你會看到,強迫將資源鎖定,使他們成為”all-or-nothing“(要麼統統獲得,要麼統統沒有),可以阻止死鎖的發生。