Linux下实现哲学家就餐问题

本文详细阐述了哲学家进餐问题在多线程编程中的应用,通过使用信号量实现线程间的同步与互斥,有效解决了死锁问题。具体介绍了偶数号和奇数号哲学家就餐的算法逻辑,并提供了Linux环境下实现该问题的代码实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哲学家进餐问题是一个多线程运用的经典例子,涉及到线程同步/互斥,临界区访问问题以及一个避免死锁的解决方法。

有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之间有一支筷子,这样每个哲学家左右各有一支筷子。哲学家有2个状态,思考或者拿起筷子吃饭。如果哲学家拿到一只筷子,不能吃饭,直到拿到2只才能吃饭,并且一次只能拿起身边的一支筷子。一旦拿起便不会放下筷子直到把饭吃完,此时才把这双筷子放回原处。如果,很不幸地,每个哲学家拿起他或她左边的筷子,那么就没有人可以吃到饭了。这就会造成死锁了。这是需要坚决杜绝的,正如操作系统的死锁问题。

编号为i的哲学家就餐的算法如下:   

While(true){
	If( i  %  2 == 0){			//偶数号哲学家
		P(左边筷子对应的信号量)
			P(右边筷子对应的信号量)
			拿起两只筷子吃饭
			V(右边筷子对应的信号量)
			V(左边筷子对应的信号量)
	}else{					//奇数号哲学家
		P(右边筷子对应的信号量)
			P(左边筷子对应的信号量)
			拿起两只筷子吃饭
			V(左边筷子对应的信号量)
			V(右边筷子对应的信号量)
	}
	吃饱后随意的睡上一段时间
}

在Linux下实现的具体代码如下:

#include <iostream>
#include <cstdio>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#define N 6
#define LEFT i
#define RIGHT (i+1) % N
using namespace std;

class Semaphore {
	private:
		sem_t sem;
	public:
		Semaphore(int value = 1) {
			sem_init(&sem,0,value); //初始化信号量,0表示信号量在线程间共享
		}
		void P() {
			sem_wait(&sem); //等待信号,获取拥有权
		}
		void V() {
			sem_post(&sem); //释放信号,释放拥有权
		}
};

Semaphore mutex[N];
pthread_t thread[N];

int id[N];
void* solve(void* param) {
	int i = *((int*)param);
	while(1) {
		if(i % 2 == 0) {
			mutex[LEFT].P();
			mutex[RIGHT].P();
			printf("哲学家%d就餐\n",i+1);
			mutex[RIGHT].V();
			mutex[LEFT].V();
		}else {
			mutex[RIGHT].P();
			mutex[LEFT].P();
			printf("哲学家%d就餐\n",i+1);
			mutex[LEFT].V();
			mutex[RIGHT].V();
		}
		sleep(1); //线程等待
	}
	pthread_exit(NULL); //结束线程
}
void thread_create() { //进程创建
	int tmp;
	for(int i = 0; i < N; i++) {
		tmp = pthread_create(&thread[i],NULL,solve,&id[i]);
		if(tmp != 0) {
			printf("线程%d创建失败\n",i);
		}
	}
}
void thread_wait() {
	for(int i = 0; i < N; i++) {
		pthread_join(thread[i],NULL);
		printf("线程%d结束\n",i);
	}
}
int main() {
	for(int i = 0; i < N; i++) {
		id[i] = i;
	}
	thread_create();
	thread_wait();
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值