Linux 多线程同步之哲学家用餐问题

博客讨论了Linux环境下解决哲学家就餐问题的多线程同步策略,通过信号量实现避免死锁。文章提出,只有当哲学家左右筷子均可获取时才允许进餐,并分析了不同情况下的信号量使用,如全用`sem_wait`可能导致死锁,而全用`sem_trywait`可能导致资源浪费。文中给出了代码示例及执行结果,展示了同步执行的过程。
摘要由CSDN通过智能技术生成

问题描述:

有五个哲学家公用一张餐桌,分别坐在周围的五张椅子上,在餐桌上有五个碗和五只筷子,他们的生活方式是交替地进行思考和用餐。平时,一个哲学家进行思考,饥饿时便试图拿取其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐,进餐完毕,放下筷子继续思考。(计算机操作系统 第三版)

书上为代码:

Var chopstick: array[0,...,4] of semaphore;
repeat
	wait(chopstick[i]);
	wait(chopstick[(i+1)%5])
			.
			.
	eat:
			.
			.
	signal(chopstick[i])
	signal(opstick[(i+1)%5])
			.
			.
	think:
until false;
这样当五个哲学家同时饥饿时而各自拿起左边的筷子是,就会使五个信号量chopstick均为0;当他们再试图去拿右边的筷子时,都将因没有筷子可拿而无限地等待。从而导致死锁。

本文解决死锁的策略是:只有当哲学家的左右两只筷子均可以用的时候,才允许其拿起筷子进餐,否则则该哲学家一直请求左边的筷子保持阻塞状态(左边的筷子信号量为1则直接占有,信号量为0则进入阻塞状态),右边的筷子若信号量为0,则非阻塞,进入等待。


详细代码:

/*
 * philosopher.c
 *
 *  Created on: 2012-12-17
 *      Author: xkey
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>

#define PEOPLE_NUM 5
#define THINKING 1
#define HUNGRY 2
#define EATING 3

sem_t chopsticks[PEOPLE_NUM];
pthread_mutex_t mutex;

void *philosopher(void *arg){
	int id = (int) arg;

	int state = THINKING;
	int right = (id + 1) % PEOPLE_NUM;
	int left = (id + PEOPLE_NUM - 1) % PEOPLE_NUM;
	char ptrState[32];

	while(1){
		switch(state){
		case THINK
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哲学家问题是一个经典的并发编程问题,用来展示多线程编程中的死锁和竞争条件等问题。下面是一个使用C++多线程解决哲学家问题的示例代码: ```c++ #include <iostream> #include <thread> #include <mutex> using namespace std; const int kNumPhilosophers = 5; // 哲学家 mutex forks[kNumPhilosophers]; // 叉子锁 void philosopher(int id) { int left_fork = id; int right_fork = (id + 1) % kNumPhilosophers; // 模拟哲学家思考 cout << "Philosopher " << id << " is thinking." << endl; this_thread::sleep_for(chrono::seconds(1)); // 尝试获得叉子 cout << "Philosopher " << id << " is hungry and wants to eat." << endl; forks[left_fork].lock(); forks[right_fork].lock(); // 开始就 cout << "Philosopher " << id << " is eating." << endl; this_thread::sleep_for(chrono::seconds(1)); // 释放叉子 forks[right_fork].unlock(); forks[left_fork].unlock(); // 就结束 cout << "Philosopher " << id << " finished eating and is thinking again." << endl; } int main() { // 创建哲学家线程 thread philosophers[kNumPhilosophers]; for (int i = 0; i < kNumPhilosophers; i++) { philosophers[i] = thread(philosopher, i); } // 等待所有哲学家线程结束 for (int i = 0; i < kNumPhilosophers; i++) { philosophers[i].join(); } return 0; } ``` 在这个示例代码中,我们使用了`mutex`来实现叉子的锁机制,每个哲学家线程都会先尝试获得左边和右边的叉子,如果获得成功就开始就,否则就会等待。这个示例代码简单易懂,但是仍然存在死锁和竞争条件等问题,需要一步的优化和改

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值