哲學家就餐問題詳解
2.23 哲學家就餐問題
1965年由Dijkstra提出
問題描述
- 5個哲學家圍坐圓桌
- 5只餐叉間隔擺放
- 哲學家行為為思考或進餐
- 哲學家進餐必須同時使用兩邊的餐叉
- 思考時蔣餐叉放回原處
- 兩個哲學家不使用同一把叉子
- 儘量避免死鎖和飢餓
如圖
方案一 取左叉
都去拿左邊的叉子,死鎖
semaphore fork[5] = {1, 1, 1, 1, 1};
void main()
{
cobegin {philosopher(0);
philosopher(1);
philosopher(2);
philosopher(3);
philosopher(4);
}coend;
}
void philosopher(int i)
{
while(true) {
think; //思考
wait(fork[i]); //拿起左邊的叉子
wait(fork[(i+1)%5]); //拿起右邊的叉子
eat();
signal(fork[i]); //放回左邊的叉子
signal(fork[(i+1)%5]); //放回右邊的叉子
}
}
方案二
請求同時拿兩個叉子,被佔則等待隨機事件再請求,可能活鎖
semaphore fork[5] = {1, 1, 1, 1, 1};
void main()
{
cobegin {philosopher(0);
philosopher(1);
philosopher(2);
philosopher(3);
philosopher(4);
}coend;
}
void philosopher(int i)
{
while(true) {
think; //思考
wait(fork[i]); //拿起左邊的叉子
timeout(wait(fork[(i+1)%5], [0, T]) //若右邊的叉子被佔用,則放下左邊叉,等待一段隨機時間後再拿
eat();
signal(fork[i]); //放回左邊的叉子
signal(fork[(i+1)%5]); //放回右邊的叉子
}
}
方案三 資源分級
為資源(這裡是餐叉)分配一個偏序(partial order)或者分級(hierarchy)的關係,並約定所有資源都按照這種順序獲取,按相反順序釋放,而且保證不會有兩個無關資源同時被同一項工作所需要
① 為餐叉編號
- 就餐前,先取用編號較低的餐叉,再取用編號較高的餐叉
- 就餐畢,先放下編號較高的餐叉,再放下編號較低的餐叉
semaphore fork[5] = {1, 1, 1, 1, 1};
void main()
{
cobegin {philosopher(0);
philosopher(1);
philosopher(2);
philosopher(3);
philosopher(4);
}coend;
}
void philosopher(int i)
{
while(true) {
think(); //思考
if (i != 4) {
wait(fork[i]); wait(fork[(i+1)%5]);} //先左後右
else {
wait(fork[(i+1)%5]); wait(fork[i]);} //先右後左
eat();
if (i != 4) {
signal(fork[(i+1)%5]); signal(fork[i]);} //先右後左
else {
signal(fork[i]); signal(fork[(i+1)%5]);} //先左後右
}
}
② 為哲學家編號
- 奇數號的哲學家必須首先拿左邊的餐叉
- 偶數號的哲學家必須首先拿右邊的餐叉
semaphore fork[5] = {1, 1, 1, 1, 1};
void main()
{
cobegin {philosopher(0);
philosopher(1);
philosopher(2);
philosopher(3);
philosopher(4);
}coend;
}
void philosopher(int i)
{
while(true) {
think(); //思考
if (i % 2 != 0) {
wait(fork[i]); wait(fork[(i+1)%5]);} //先左後右
else {
wait(fork[(i+1)%5]); wait(fork[i]);}
eat();
signal(fork[(i+1)%5]); //先右後左
signal(fork[i]);
}
}
方案四 服務生方法
- 引入一個餐廳服務生,哲學家必須經過他的允許才能拿起餐叉
- 最多允許4個哲學家同時進食
semaphore fork[5] = {1, 1, 1, 1, 1}, room = 4;
void main()
{
cobegin {philosopher(0);
philosopher(1);
philosopher(2);
philosopher(3);
philosopher(4);
}coend;
}
void philosopher(int i)
{
while(true) {
think; //思考
wait(room); //佔據就餐位置
wait(fork[i]); //拿起左邊的叉子
wait(fork[(i+1)%5]); //拿起右邊的叉子
signal(fork[i]); //放回左邊的叉子
signal(fork[(i+1)%5]); //放回右邊的叉子
signal(room); //釋放就餐位置
}
}
引申:And型訊號量集
- 在一個原語中申請需要的多個臨界資源,要麼全部分,要麼一個都不分配
- AND型訊號量集P原語為Swait(Simultaneous Wait),V原語為Ssignal(Simultaneous Signal)。
- Swait(S1, S2, …, Sn)
- Ssignal(S1, S2, …, Sn)
管程方案
monitor dining controller;
cond ForkReady [5]; /*condition variable for synchronization */
boolean fork[ 5]={ true } ; /*availability status of each fork*/
void get_forks (int pid) /*pid is the philosopher id number */
{
int left = pid;
int right =(++pid)%5;
/*grant the left fork*/
if( ! fork [ left])
cwait(ForkReady [ left] ); /*queue on condition variable */
fork [ left]= false ;
/*grant the right fork*/
if( ! fork [ right] )
cwait(ForkReady [right] );
/*queue on condition variable */
fork [ right] = false;
}
void release_forks ( int pid){
int left = pid;
int right =(++pid)%5;
/*release the left fork*/
if( empty (ForkReady [ leftl) /*no one is waiting for this fork */
fork [ left] = true;
else /*awaken a process waiting on this fork */
csignal (ForkReady [ left]);
/*release the right fork*/
if (empty (ForkReady [right]) /*no one is waiting for this fork*/
fork [ right]= true;
else /*awaken a process waiting on this fork*/
csignal (ForkReady [right] );
}
void philosopher [ k=0 to 4] /*the five philosopher clients */
{
while (true){
<think>;
get_forks (k); /*client requests two forks via monitor * /
<eat spaghetti>;
release_forks (k); /*client releases forks via the monitor */
}
}
相關文章
- java實現pv操作 -------哲學家問題Java
- 用c++設計哲學家進餐問題的求解C++
- AI助攻「菜鳥數學家」解決忙碌海狸問題,陶哲軒轉發分享AI
- 機器學習,詳解SVM軟間隔與對偶問題機器學習
- Python異常 ValueError的問題詳解PythonError
- TCP協議粘包問題詳解TCP協議
- CAS原理分析及ABA問題詳解
- 看看哲學家如何使用“遊戲”這一概念遊戲
- flutter安裝詳解--初體驗--問題解決Flutter
- web開發的跨域問題詳解Web跨域
- Google研究主管:非技術專家如何利用機器學習解決問題Go機器學習
- 哲學家啟動研究 :數學是發明還是發現?- dailynousAI
- web安全機制問題詳解之二:CSRFWeb
- 多執行緒併發安全問題詳解執行緒
- 前端進階課程之跨域問題詳解前端跨域
- web安全機制問題詳解之一:XSSWeb
- 洛谷 p1605 迷宮問題 詳解
- Navigation問題詳解——Fragment建立新的例項NavigationFragment
- mount命令詳解及常見問題彙總
- 【原創】視訊+文字:詳解VBA解決數獨問題
- 雲解析專家講解DNS解析生效時間問題DNS
- 去留無意,去留爺爺,是去還是留,這是一個哲學問題?
- 密碼學專家揭示Telegram Passport中的安全問題密碼學Passport
- 混合專家模型 (MoE) 詳解模型
- Python詞雲庫wordcloud中文顯示問題詳解PythonCloud
- 一文詳解資料科學家的必備技能資料科學
- 《生活的哲學》
- 哲學筆記筆記
- 機器學習策略篇:詳解處理資料不匹配問題(Addressing data mismatch)機器學習
- 詳解nginx代理天地圖做快取解決跨域問題Nginx地圖快取跨域
- java學習中問題與解決方式Java
- munium學習過程中問題解決
- 電腦科學哲學(史丹佛大學哲學百科全書)
- PLM系統到底解決了哪些問題?詳細解析
- 一文詳解面試常考的TopK問題面試TopK
- 詳解JAVA執行緒問題診斷工具Thread DumpJava執行緒thread
- 解析SQLite中的常見問題與總結詳解SQLite
- i.MX8MQ自制底板無PCIe問題詳解MQ