哲學家喫飯問題2019-8-26

轉載鏈接:https://blog.csdn.net/hj605635529/article/details/73064877

有五個哲學家公用一張餐桌,分別坐在周圍的五張椅子上,在餐桌上有五個碗和五隻筷子,他們的生活方式是交替地進行思考和用餐。平時,一個哲學家進行思考,飢餓時便試圖拿取其左右最靠近他的筷子,只有在他拿到兩隻筷子時才能進餐,進餐完畢,放下筷子繼續思考。

思路:

選用互斥鎖mutex,如創建5個, pthread_mutex_t m[5];
模型抽象:
5個哲學家 --> 5個線程; 5支筷子 --> 5把互斥鎖 int left(左手), right(右手)
5個哲學家使用相同的邏輯,可通用一個線程主函數,void *tfn(void *arg),使用參數來表示線程編號:int i = (int)arg;
哲學家線程根據編號知道自己是第幾個哲學家,而後選定鎖,鎖住,喫飯。否則哲學家thinking。
A B C D E
5支筷子,在邏輯上形成環: 0 1 2 3 4 分別對應5個哲學家:

所以有:
if(i == 4)
left = i, right = 0;
else
left = i, right = i+1;
振盪:如果每個人都攥着自己左手的鎖,嘗試去拿右手鎖,拿不到則將鎖釋放。過會兒五個人又同時再攥着左手鎖嘗試拿右手鎖,依然拿不到。如此往復形成另外一種極端死鎖的現象——振盪。
避免振盪現象:只需5個人中,任意一個人,拿鎖的方向與其他人相逆即可(如:E,原來:左:4,右:0 現在:左:0, 右:4)。
所以以上if else語句應改爲:
if(i == 4)
left = 0, right = i;
else
left = i, right = i+1;
而後, 首先應讓哲學家嘗試加左手鎖:
while {
pthread_mutex_lock(&m[left]); 如果加鎖成功,函數返回再加右手鎖,
如果失敗,應立即釋放左手鎖,等待。
若,左右手都加鎖成功 --> 喫 --> 喫完 --> 釋放鎖(應先釋放右手、再釋放左手,是加鎖順序的逆序)
}
主線程(main)中,初始化5把鎖,銷燬5把鎖,創建5個線程(並將i傳遞給線程主函數),回收5個線程。
避免死鎖的方法:

  1. 當得不到所有所需資源時,放棄已經獲得的資源,等待。
  2. 保證資源的獲取順序,要求每個線程獲取資源的順序一致。如:A獲取順序1、2、3;B順序應也是1、2、3。若B爲3、2、1則易出現死鎖現象。

代碼:

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
 
 
pthread_mutex_t chopstick[5]; //5把鎖,也就是5根筷子。
 
void*tfn(void *arg)
{
	int i = (int)arg;
 
	int left,right;  //左右筷子的編號。
 
	if(i == 4)
	{
		left = 0;
		right = i;
	}
	else
	{
		left = i;
		right = i+1;
	}
 
	while(1)
	{
		sleep(1);  //思考
		pthread_mutex_lock(&chopstick[left]); //拿到左手的筷子。
		printf("philosopher %d fetches chopstick %d\n",i,left);
		if(pthread_mutex_trylock(&chopstick[right]) != 0 )//拿右手的筷子失敗
		{
			pthread_mutex_unlock(&chopstick[left]); //右手筷子被拿走,放下左手的筷子。
			continue;
		}
 
		printf("philosopher %d fetches chopstick %d\n",i,right);
		printf("philosopher %d is eating.\n",i);
		sleep(2);  //喫飯
 
		pthread_mutex_unlock(&chopstick[right]); //放下右手的筷子。
		printf("philosopher %d release chopstick %d\n",i,right);
 
		pthread_mutex_unlock(&chopstick[left]); //放下右手的筷子。
		printf("philosopher %d release chopstick %d\n",i,left);
 
	}
}
int main()
{
	pthread_t tid[5]; //5個哲學家
 
	int i ;
	for(i = 0; i < 5; ++i)
	{
		pthread_mutex_init(&chopstick[i],NULL);
		pthread_create(&tid[i],NULL,tfn,(void*)i);
	}
 
 
	for( i = 0; i < 5; ++i)
	{
		pthread_join(tid[i],NULL);
	}
 
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章