linux下使用线程锁解决哲学家问题

问题:5个哲学家围坐在一个圆桌上,每两个哲学家之间都有一只筷子,哲学家平时进行思考,只有当他们饥饿时,才拿起筷子吃  饭。规定每个哲学家只能先取其左边筷子,然后取其右边筷子,然后才可以吃饭。

要求:使用线程锁、思考时间随机。

思路:定义数组表示五双筷子,1表示空闲状态,0表示使用状态。

int state[N] = {1,1,1,1,1};

          在线程函数中,只需要循环进行吃饭、思考就好。问题在于如何拿放筷子。

while(1)
	{
		printf("哲学家%d在思考!!\n",id);	
		sleep(5);
		
		take_forks(id);				
		
		printf("哲学家%d在吃饭~~\n",id);		
		sleep(2);
		
		put_forks(id);					
	}

     对于可能产生的死锁问题,我们采用当两边筷子同时空闲时取用。否则一直等待。

if(state[id]==1&&state[(id+1)%N]==1)					
	{
		pthread_mutex_lock(&mutex);					
		state[id]=0;
		state[(id+1)%N]=0;
		pthread_mutex_unlock(&mutex);						
    }
	else 												
		;

       最终代码:

#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>          

#define N 5													//定义哲学家数量为5人

int state[N] = {1,1,1,1,1};									//定义数组,用于表示五个筷子的使用情况,1代表空闲,0表示在使用

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;			//定义线程锁,用于state变量的锁

void take_forks(int id)										//拿起筷子函数
{
	if(state[id]==1&&state[(id+1)%N]==1)					//当左边筷子与右边筷子同时空闲时,拿起(置0)
	{
		pthread_mutex_lock(&mutex);							//打开线程锁,使其他线程不能对state进行修改
		state[id]=0;
		state[(id+1)%N]=0;
		pthread_mutex_unlock(&mutex);						//释放线程锁,使其他线程可以对state进行修改
	}
	else 													//否则一直执行空指令,等待同时空闲状态
		;
}
void put_forks(int id)										//将左边筷子与右边筷子同时放下(置1)
{
	pthread_mutex_lock(&mutex);
	state[id]=1;
	state[(id+1)%N]=1;
	pthread_mutex_unlock(&mutex);
}

void *philosopher(void *arg)								//线程执行函数
{
	int id=*(int *)arg;										//将哲学家编号,强制装换为int类型
	srand( (unsigned)time( NULL ) );          				//初始化随机数
	while(1)
	{
		int time_s = rand()%5+1;
		//int time_s = 5;
		printf("哲学家%d在思考 %d秒!!\n",id,time_s);					//思考5秒
		sleep(time_s);
		
		take_forks(id);										//拿起筷子
		
		printf("哲学家%d在吃饭~~\n",id);					//吃饭2秒
		sleep(2);
		
		put_forks(id);										//放下筷子继续思考
	}
}

int main()
{
	int i,id[N];
	pthread_t phi[N];										//定义线程标识符数组
	for(i=0;i<N;i++)										//绑定线程函数
	{
		id[i]=i;
		pthread_create(&phi[i],NULL,philosopher,(void *)&id[i]);
	}
	for(i=0;i<N;i++)										//释放线程资源
	{
		pthread_join(phi[i],NULL);
	}
	return 0;
}

        运行结果如下:

      用于作为学习笔记,这是我们一次的嵌入式作业。能力有限,可能存在考虑不及的问题,望大神指点优化!

      闲着没事,又尝试了其他的方法:

     定义多个线程锁,使之作为哲学家所使用的筷子。

pthread_mutex_t mutex[N]={PTHREAD_MUTEX_INITIALIZER};	

     直接使之进行左右筷子的抢夺。

	while(1)
	{
		//int time_s = rand()%5+1;
		int time_s = 5;
		printf("哲学家%d在思考 %d秒!!\n",id,time_s);					//思考5秒
		sleep(time_s);
		
		pthread_mutex_lock(&mutex_flag);
		pthread_mutex_lock(&mutex[(id+1)%N]);
		
		printf("哲学家%d在吃饭~~\n",id);					//吃饭2秒
		sleep(2);
		
		pthread_mutex_unlock(&mutex[id]);
		pthread_mutex_unlock(&mutex[(id+1)%N]);
		
	}

        这又牵扯到了可能会产生死锁的问题。继续进行解决。

        1、再加一把锁,使之每次只能一人进餐。

while(1)
	{
		//int time_s = rand()%5+1;
		int time_s = 5;
		printf("哲学家%d在思考 %d秒!!\n",id,time_s);					//思考5秒
		sleep(time_s);
		
		pthread_mutex_lock(&mutex_flag);

		pthread_mutex_lock(&mutex[id]);
		pthread_mutex_lock(&mutex[(id+1)%N]);
		
		printf("哲学家%d在吃饭~~\n",id);					//吃饭2秒
		sleep(2);
		
		pthread_mutex_unlock(&mutex[id]);
		pthread_mutex_unlock(&mutex[(id+1)%N]);
		
		pthread_mutex_unlock(&mutex_flag);
	}

          这种方式的缺点很显然,就是每次只能有一人进餐。

         运行结果如下:

    2、最多允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。

         我们在全局加一个变量,flag使之表示正在占用筷子的人数。判断如果使用筷子的人数大于等于4时,便退出执行。

while(1)
	{
		//int time_s = rand()%5+1;
		int time_s = 5;
		printf("哲学家%d在思考 %d秒!!\n",id,time_s);					//思考5秒
		sleep(time_s);
		
		if(flag >=4)
		{
			printf("falg >= 4\n");
			continue;
		}
		pthread_mutex_lock(&mutex_flag);					//用餐人数加一
			flag++;
		pthread_mutex_unlock(&mutex_flag);
		
		pthread_mutex_lock(&mutex[id]);
		pthread_mutex_lock(&mutex[(id+1)%N]);
		
		printf("哲学家%d在吃饭~~\n",id);					//吃饭2秒
		sleep(2);
		
		pthread_mutex_unlock(&mutex[id]);
		pthread_mutex_unlock(&mutex[(id+1)%N]);
		
		pthread_mutex_lock(&mutex_flag);					//用餐人数减一
			flag--;
		pthread_mutex_unlock(&mutex_flag);
	}

       嗯,这种方法可行!

Guess you like

Origin blog.csdn.net/TiAmo_99/article/details/106125007