哲学家就餐问题
多线程编程中,常常会遇到线程间访问共享资源的问题,如果处理不当则会发生死锁,某一个线程可能永远访问不到共享资源。
为了避免死锁的发生,提出哲学家就餐问题。
下面展示一些代码片段
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/mman.h>/* 多线程之间通过互斥锁实现哲学家就餐问题(如何避免死锁) 得到两把锁则进餐,只得到第一把锁,得不到第二把锁则释放已经拥有的第一把锁*/
pthread_mutex_t mutex[5];void *tfun(void *arg)
{int left,right;int i = (int)arg;int ret;if(i == 4){left = 0,right = i;}else{left = i;right = i+1;}while(1){pthread_mutex_lock(&mutex[left]);//利用trylock非阻塞函数,加锁失败则立即返回,不则塞ret = pthread_mutex_trylock(&mutex[right]);if(ret == 0){printf("%dth thread get lock\n",i);sleep(1); //模拟哲学家进餐过程pthread_mutex_unlock(&mutex[right]);printf("%dth thread unlock right %d----------------\n",i,right);pthread_mutex_unlock(&mutex[left]);printf("%dth thread unlock left %d----------------\n",i,left);sleep(1);}else{pthread_mutex_unlock(&mutex[left]);printf("%dth thread unlock left %d-----------------------------------\n",i,left);sleep(1);}}pthread_exit(NULL);
}int main()
{pthread_t tid[5];//定义五个互斥锁-对应5只筷子int i;for(i=0;i<5;i++){//互斥锁初始化pthread_mutex_init(&mutex[i],NULL);}for(i=0;i<5;i++){//创建五个线程--对应5个哲学家。编号为0-4pthread_create(&tid[i],NULL,tfun,(void *)i);}for(i=0;i<5;i++){pthread_join(tid[i],NULL);}for(i=0;i<5;i++){pthread_mutex_destroy(&mutex[i]);}return 0;
}
振荡:如果每个人都攥着自己左手的锁,尝试去拿右手锁,拿不到则将锁释放。过会儿五个人又同时再攥着左手锁尝试拿右手锁,依然拿不到。如此往复形成另外一种极端死锁的现象——振荡。
程序中哲学家都先去拿左边的筷子,再拿右边的筷子,为了避免振荡,第四个哲学家反其道而行,先拿右边的筷子,再拿左边的筷子。
两个筷子都拿到则进餐,如果只拿到第一个筷子,没有拿到第二个筷子,则释放已有的筷子。
避免死锁的方法:
1:若得不到所有所需的资源时,放弃已经获得的资源,等待。
2:保证资源的获取顺序,要求每个线程获取资源的顺序一致,如:A获取顺序1、2、3;B顺序也应该是1、2、3.若B为3、2、1则易出现死锁的现象。