①總體思路:
都去拿左邊的筷子,並且最后一個人不能去拿筷子(防止大家都拿了左邊的筷子,沒有右邊的筷子,導致死鎖了),解決死鎖問題的辦法就是同時只允許四位哲學家同時拿起同一邊的筷子,這樣就能保證一定會有一位哲學家能夠拿起兩根筷子完成進食並釋放資源,供其他哲學家使用,從而實現永動,避免了死鎖。舉個最簡單的栗子,假定0~3號哲學家已經拿起了他左邊的筷子,然后當4號哲學家企圖去拿他左邊的筷子的時候,將該哲學家的線程鎖住,使其拿不到其左邊的筷子,然后其左邊的筷子就可以被3號哲學家拿到,然后3號哲學家進餐,釋放筷子,然后更多的哲學家拿到筷子並進餐。
如何才能實現當4號哲學家企圖拿起其左邊的筷子的時候將該哲學家的線程阻塞?這個時候就要用到該問題的提出者迪傑斯特拉(這貨還提出了迪傑斯特拉最短路徑算法,著名的銀行家算法也是他發明的)提出的信號量機制。因為同時只允許有四位哲學家同時拿起左筷子,因此我們可以設置一個信號量r,使其初始值為4,然后每當一位哲學家企圖去拿起他左邊的筷子的時候,先對信號量做一次P操作,從而當第五位哲學家企圖去拿做筷子的時候,對r做一次P操作,r = -1,由r < 0得第五位哲學家的線程被阻塞,從而不能拿起左筷子,因此也就避免了死鎖問題。然后當哲學家放下他左邊的筷子的時候,就對r做一次V操作。
②在主線程和子線程中,避免了競爭關系.
代碼參考如下:
/***********************************
* @file linux_zexuejia.c
* @copyright 月光下的腳步 Co.,Ltd.ALL Right Reserved
* @brief 使用信號量和互斥鎖完成,哲學家就餐問題。
* @author 王有康
* @data 2019、7、31
* @version V1.1
* @Last Modified 2018/10/25 wangyoukang
* @note 當前版本是v1.1版本,以后需要修改,可以在上添加版本和修改日期
* @note
* @warning
* @Function List :
************************************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define N 5
//互斥鎖
pthread_mutex_t chops[N];
//信號量
sem_t r;
/**********************
* @fn philosopher
* @biref 每次只有4個人能夠獲得左手資源,這樣不會死鎖
* @param philosopher number
* @return
* @other
***********************/
void philosopher(void *arg)
{
int i = *(int *)arg;
int left = i;
int right = (i + 1)%N;
while(1)
{
printf("哲學家%d在思考問題\n",i);
usleep(1000);
printf("哲學家%d餓了\n",i);
sem_wait(&r);
pthread_mutex_lock(&chops[left]);
printf("philosopher %d take left lock\n",i);
pthread_mutex_lock(&chops[right]);
printf("philosopher %d take right lock\n",i);
printf("philosopher %d eat\n",i);
usleep(1000);
pthread_mutex_unlock(&chops[right]);
printf("philosopher %d release right lock\n",i);
pthread_mutex_unlock(&chops[left]);
printf("philosopher %d realease left lock\n",i);
sem_post(&r);
}
}
/**********************
* @fn philosopher
* @biref 主函數
* @param
* @return
* @other
***********************/
int main(int argc,char **argv)
{
int i = 0,*ptr;
pthread_t tid[N];
for(i = 0;i < N;i++)
{
pthread_mutex_init(&chops[i],NULL);
}
sem_init(&r,0,4);
for(i = 0;i < N;i++)
{
//防止主線程和對等線程競爭
ptr = malloc(sizeof(int));
*ptr = i;
pthread_create(&tid[i],NULL,(void *)philosopher,&i);
}
for( i = 0;i< N;i++)
{
pthread_join(tid[i],NULL);
}
for(i = 0;i < N;i++)
{
pthread_mutex_destroy(&chops[i]);
}
sem_destroy(&r);
return 0;
}
