死結(deadlock)
想像兩個有禮貌的人在一道窄門相遇。各自往旁邊讓開好讓對方先過,但兩人往同一邊讓,於是互相擋住,又退回去,再試一次,如此沒完沒了。現在把他們從有禮貌換成固執:兩人各抓住同一把梯子的一端,而且非要也拿到另一端才肯放手,於是誰也不會再動。這種永遠卡死、每個人都在等只有別人才能放掉的東西的局面,就是死結。
在作業系統裡,「人」是行程(process,或執行緒),而「門」或「梯子」是資源:印表機、檔案鎖、一段記憶體、一列資料庫紀錄。死結是這樣一種狀態:一組行程全都被阻塞,每一個都在等著取得某個資源,而那個資源目前正被同一組裡的另一個行程持有。因為每個人需要的資源都握在另一個成員手上,而誰都要先拿到其餘的才肯放掉手上的,於是沒有人能前進。關鍵在於這種等待是循環且永久的:這組裡的任何東西都無法自行解開,除非外力(作業系統、逾時機制、人)介入,否則它們會永遠等下去。
死結之所以重要,是因為它安靜而徹底——受影響的行程不會當掉、不丟錯誤、也不耗用 CPU,就只是卡住,而且常把共享資源扣為人質,連帶凍結其他需要這些資源的工作。它也是少數可能只在特定事件時序下才出現的臭蟲之一,因此能通過所有測試,卻在正式環境發作。死結並不等於行程只是跑得慢,也不等於活結或飢餓(另行說明):真正的死結中存在一組固定的行程,無論你等多久,它們永遠不會有任何進展。
行程 A 持有鎖 L1,接著要求 L2;就在同時,行程 B 持有 L2,接著要求 L1。A 等 B 放掉 L2;B 等 A 放掉 L1。在拿到自己等待的鎖之前誰都不肯放手,於是兩者永遠等下去——一個雙行程死結。
經典的雙鎖死結:每個行程都持有對方需要的東西,又在等對方持有的東西。
死結需要一組固定的行程全部永遠卡住;若某行程只是等很久但終究能前進,那是緩慢或飢餓,而非死結。要使死結成為可能,四個必要條件必須同時成立。