經典同步問題與並行程式設計

哲學家用餐問題(dining philosophers problem)

/ Dijkstra -> DYKE-struh /

五位哲學家圍坐在圓桌旁。每對鄰座之間放著一根筷子——五根筷子配五位哲學家。哲學家不是在思考就是在用餐,而要吃一碗麵,他需要左手邊和右手邊兩根筷子。麻煩在於每根筷子都和一位鄰座共用,所以相鄰的兩位哲學家永遠不能同時進食。這場小晚宴由 Dijkstra 於 1965 年提出,是整個電腦科學中最著名的例子,用來說明一群人共用有限資源時,如何可能徹底卡死。

災難是這樣發生的。假設每位哲學家都遵守同一條簡單規則:先拿左邊的筷子,再拿右邊的筷子。現在想像五位在完全相同的一刻全餓了。每位都拿起左邊那根筷子——此刻桌上每根筷子都被握著。每位哲學家都在等右邊那根,而那正是鄰座的左邊那根,鄰座永遠不會放下,因為他同樣在等。沒有人能吃、沒有人會放手,所有人就這樣永遠坐著。這就是死結,而四個必要條件全部齊備:每根筷子被獨佔(互斥)、每位哲學家握著一根並等待另一根(持有並等待)、沒有人能被迫放下筷子(不可剝奪),而等待沿著桌子繞成完美的一圈(循環等待)。

解法即是教訓,而每一個都打破一個不同的條件。資源排序:把筷子編號,要求每個人先拿編號較小的那根——此時某位哲學家會和鄰座搶同一根筷子,圈被打斷,死結便無法形成。仲裁者(一位侍者):哲學家拿任何筷子前都得先向侍者請求許可,而侍者乾脆不讓五位同時搶。限制座位:一次最多只准四位哲學家上桌,於是至少永遠有一根筷子是空的。每一招都是真正可遷移的技術,用來防止並行程式卡死。

資源排序解法:把筷子編號 0 到 4。哲學家 i 通常先拿筷子 i 再拿 i+1,但哲學家 4(位於筷子 4 與筷子 0 之間)必須先拿筷子 0。如此一來,不可能所有人同時搶到自己左邊的筷子,循環便永遠合不攏。

對資源取得施加一個全域順序以打破循環等待——使用最廣的死結預防技巧。

天真的「乾脆同時拿兩根」或隨機重試的解法,可能把死結換成活結:五位反覆拿起一根,發現拿不到第二根,又放回去,再以完美的同步重試——永遠忙碌,永遠吃不到。

又称
五位哲學家問題dining philosophers