問題描述
哲學家就餐問題也被稱為刀叉問題,或者吃麵問題。我們先來描述一下這個問題所要說明的事情,這個問題如下圖所示:
有 5 個哲學家,他們面前都有一雙筷子,即左手有一根筷子,右手有一根筷子。當然,這個問題有多個版本的描述,可以說是筷子,也可以說是一刀一叉,因為吃牛排的時候,需要刀和叉,缺一不可,也有說是用兩把叉子來吃義大利面。這裡具體是刀叉還是筷子並不重要,重要的是必須要同時持有左右兩邊的兩個才行,也就是說,哲學家左手要拿到一根筷子,右手也要拿到一根筷子,在這種情況下哲學家才能吃飯。為了方便理解,我們選取和我國傳統最貼近的筷子來說明這個問題。
主流程
我們來看一下哲學家就餐的主流程。哲學家如果想吃飯,他會先嘗試拿起左手的筷子,然後再嘗試拿起右手的筷子,如果某一根筷子被別人使用了,他就得等待他人用完,用完之後他人自然會把筷子放回原位,接著他把筷子拿起來就可以吃了(不考慮衛生問題)。這就是哲學家就餐的最主要流程。
流程的偽**
根據我們的邏輯規定,在拿起左手邊的筷子之後,下一步是去拿右手的筷子。大部分情況下,右邊的哲學家正在思考,所以當前哲學家的右手邊的筷子是空閒的,或者如果右邊的哲學家正在吃飯,那麼當前的哲學家就等右邊的哲學家吃完飯並釋放筷子,於是當前哲學家就能拿到了他右手邊的筷子了。
但是,如果每個哲學家都同時拿起左手的筷子,那麼就形成了環形依賴,在這種特殊的情況下,每個人都拿著左手的筷子,都缺少右手的筷子,那麼就沒有人可以開始吃飯了,自然也就沒有人會放下手中的筷子。這就陷入了死鎖,形成了乙個相互等待的情況。**如下所示:
/**
* @author wgr
* @create 2021/1/29 -- 14:08
*/public class testdeadlock
}@slf4j(topic = "c.philosopher")
class philosopher extends thread
@override
public void run() }}
}random random = new random();
private void eat()
}class chopstick
@override
public string tostring() ';}}
結果:
活鎖
活鎖出現在兩個執行緒互相改變對方的結束條件,最後誰也無法結束,例如
/**
* @author wgr
* @create 2021/1/29 -- 14:22
*/@slf4j(topic = "c.testlivelock")
public class testlivelock ", count);
}}, "t1").start();
new thread(() -> ", count);
}}, "t2").start();}}
飢餓很多教程中把飢餓定義為,乙個執行緒由於優先順序太低,始終得不到 cpu 排程執行,也不能夠結束,飢餓的情況不易演示,講讀寫鎖時會涉及飢餓問題
,先來看看使用順序加鎖的方式解決之前的死鎖問題
順序加鎖的解決方案
改變乙個哲學家拿筷子的順序
我們還可以利用死鎖避免策略,那就是從邏輯上去避免死鎖的發生,比如改變其中乙個哲學家拿筷子的順序。我們可以讓 4 個哲學家都先拿左邊的筷子再拿右邊的筷子,但是有一名哲學家與他們相反,他是先拿右邊的再拿左邊的,這樣一來就不會出現迴圈等待同一邊筷子的情況,也就不會發生死鎖了。
解決:
/**
哲學家就餐問題
本文是哲學家就餐問題在 linux 上的程式實現,與windows 平台的實現類似,程式上稍有不同。philosopherdining.cpp include include include include include include rasutil.h using namespace std ...
哲學家就餐問題
pragma once include include include include include include include include include include include include include stdafx.h handle chopstick 5 room l...
哲學家就餐問題
假設有五位哲學家圍坐在一張圓形餐桌旁,做以下兩件事情之一 吃飯,或者思考。吃東西的時候,他們就停止思考,思考的時候也停止吃東西。餐桌中間有一大碗義大利面,每兩個哲學家之間有乙隻餐叉。因為用乙隻餐叉很難吃到義大利面,所以假設哲學家必須用兩隻餐叉吃東西。他們只能使用自己左右手邊的那兩隻餐叉。哲學家就餐問...