为每一个链表(linked list)准备一个critical section之后(关于链表,请参看”Win32多线程之临界区(Critical Sections)“,我却开始了另一个问题。请看下面这个用来交换两个链表内容的函数:
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“(要么统统获得,要么统统没有),可以阻止死锁的发生。