哲学家就餐问题

哲学家就餐问题。这是由计算机科学家Dijksta提出的经典死锁场景

问题描述:有5个哲学家,这些哲学家只做两件事--思考和吃饭,他们思考的时候不需要任何共享资源,但是吃饭的时候必须使用餐具,而餐具是有限的。原版的故事里,餐具是叉子,吃饭的时候要用两把叉子把面条从碗里捞出来。很显然把叉子换成筷子更合理,所以:一个哲学家需要两根筷子才能吃饭。

现在引入问题:这些哲学家很穷,只买的起5根筷子。他们做成一圈,两个人的中间放一根筷子。哲学家吃饭的时候必须同时得到左边手和右边手的筷子。如果他们身边的任何一位正在使用筷子,那他只有等着。

假设哲学家的编号为A,B,C,D,E,筷子为1,2,3,4,5,哲学家和筷子围成一圈

序号 (哲学家) 左边 右边

A 5 1

B 1 2

C 2 3

D 3 4

E 4 5

每个哲学家均为一个单独的线程,每个线程循环左以下动作:思考rand()% 10秒,然后先拿左手边的筷子再拿右边的筷子(筷子这种资源可以用mutex表示),有任何一边拿不到就一直等着,全拿到就吃饭rand()%10秒,然后放下筷子。

编写程序仿真哲学家就餐的场景:

philosopher A fetches chopsticks 5

philosopher B fetches chopsticks 1

...................

要想不产生死锁,只能用trylock,而不能用lock,否则有可能产生阻塞

代码(有点儿繁琐):

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

pthread_mutex_t one_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t two_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t three_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t four_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t five_mutex = PTHREAD_MUTEX_INITIALIZER;


void think(void)
{
	usleep(rand() % 10);
}

void eat(void)
{
	usleep(rand() % 10);
}

void *thr_fn1(void *arg)
{
	while(1)
	{
		think();//先思考一会儿
		printf("philosopher A is thinking\n");
		if(pthread_mutex_trylock(&five_mutex) == 0)//成功获得锁5
		{
			printf("Philosopher A fetches chopstick 5\n");
			if(pthread_mutex_trylock(&one_mutex) != 0)//如果没有获得锁1
			{
				pthread_mutex_unlock(&five_mutex);//解锁5
				printf("Philosopher A releases chopstick 5\n");
				continue;//接着尝试
			}
			//成功获得锁1
			printf("Philosopher A fetches chopstick 1\n");
			eat();//成功的话就eat
			printf("philosopher A is eating\n");
			
			pthread_mutex_unlock(&five_mutex);
			pthread_mutex_unlock(&one_mutex);
			
			printf("Philosopher A releases chopstick 5 -- 1\n");
		}
		think();//不成功的话就think
	}
}

void *thr_fn2(void *arg)
{
	while(1)
	{
		think();//不成功的话就sleep
		printf("philosopher B is thinking\n");
		if(pthread_mutex_trylock(&one_mutex) == 0)//成功获得锁x
		{
			printf("Philosopher B fetches chopstick 1\n");
			if(pthread_mutex_trylock(&two_mutex) != 0)//如果没有获得锁y
			{
				pthread_mutex_unlock(&one_mutex);//解锁x
				printf("Philosopher B releases chopstick 1\n");
				continue;//接着尝试
			}
			//成功获得锁y
			printf("Philosopher B fetches chopstick 2\n");
			eat();
			printf("philosopher B is eating\n");
			
			pthread_mutex_unlock(&one_mutex);
			pthread_mutex_unlock(&two_mutex);
			
            printf("Philosopher B releases chopstick 1 -- 2\n");
		}
		
		think();//不成功的话就sleep
	}
}

void *thr_fn3(void *arg)
{
	while(1)
	{
		think();//不成功的话就sleep
		printf("philosopher C is thinking\n");
		if(pthread_mutex_trylock(&two_mutex) == 0)//成功获得锁x
		{
			printf("Philosopher C fetches chopstick 2\n");
			if(pthread_mutex_trylock(&three_mutex) != 0)//如果没有获得锁y
			{
				pthread_mutex_unlock(&two_mutex);//解锁x
				printf("Philosopher C releases chopstick 2\n");
				continue;//接着尝试
			}
			//成功获得锁y
			printf("Philosopher C fetches chopstick 3\n");
			eat();
			printf("philosopher C is eating\n");
			pthread_mutex_unlock(&two_mutex);
			pthread_mutex_unlock(&three_mutex);
			
			printf("Philosopher C releases chopstick 2 -- 3\n");
		}
		
		think();//不成功的话就sleep
	}
}

void *thr_fn4(void *arg)
{
	while(1)
	{
        think();//不成功的话就sleep
        printf("philosopher D is thinking\n");
		if(pthread_mutex_trylock(&three_mutex) == 0)//成功获得锁x
		{             
			printf("Philosopher D fetches chopstick 3\n");   
			if(pthread_mutex_trylock(&four_mutex) != 0)//如果没有获得锁y
            {
				pthread_mutex_unlock(&three_mutex);//解锁x
				printf("Philosopher D releases chopstick 3\n");
				continue;//接着尝试
			}
			//成功获得锁y
			printf("Philosopher D fetches chopstick 4\n");
			eat();
			printf("philosopher D is eating\n");
			pthread_mutex_unlock(&three_mutex);
			pthread_mutex_unlock(&four_mutex);
			
			printf("Philosopher D releases chopstick 3 -- 4\n");
		}
		
		think();//不成功的话就sleep
    }
}

void *thr_fn5(void *arg)
{
	while(1)
	{
		think();//不成功的话就sleep
		printf("philosopher E is thinking\n");
		if(pthread_mutex_trylock(&four_mutex) == 0)//成功获得锁x
		{
			printf("Philosopher E fetches chopstick 4\n");
			if(pthread_mutex_trylock(&five_mutex) != 0)//如果没有获得锁y
			{
				pthread_mutex_unlock(&four_mutex);//解锁x
				printf("Philosopher E releases chopstick 4\n");
                continue;//接着尝试
			}
			//成功获得锁y
			printf("Philosopher E fetches chopstick 5\n");
			eat();
			printf("philosopher E is eating\n");
			pthread_mutex_unlock(&four_mutex);
			pthread_mutex_unlock(&five_mutex);
			
            printf("Philosopher E releases chopstick 4 -- 5\n");
		}
		
		think();//不成功的话就sleep
	}
}
int main(void)
{
	pthread_t tid1,tid2,tid3,tid4,tid5;
	srand((unsigned int)time(NULL));
	
	pthread_create(&tid1,NULL,thr_fn1,NULL);
	pthread_create(&tid2,NULL,thr_fn2,NULL);
	pthread_create(&tid3,NULL,thr_fn3,NULL); 
    pthread_create(&tid4,NULL,thr_fn4,NULL);
	pthread_create(&tid5,NULL,thr_fn5,NULL);
	
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	pthread_join(tid3,NULL);
	pthread_join(tid4,NULL);
	pthread_join(tid5,NULL);
	
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值