经典进程的同步问题(生产者--消费者问题、哲学家进餐问题、读者--写者问题)

本文探讨了操作系统中的三个经典进程同步问题:生产者-消费者问题、哲学家进餐问题和读者-写者问题。针对这些问题,文章详细分析了各自的解决方案,包括不同方法的实现策略,如信号量机制和互斥条件,旨在确保进程间的正确协调和避免死锁的发生。
摘要由CSDN通过智能技术生成

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。点击这里

生产者–消费者问题

在这里插入图片描述

分析

  • P1~Pl 向BUFF存信息,C1~Cm 从BUFF取信息。
  • 不能对同一个信息既存又取,因此P进程和C进程互斥(mutex)
  • BUFF中有空位,P进程才能存信息(empty)
  • BUFF中有信息,C进程才能取信息(full)

实现

int in = 0, out = 0; // 在BUFF中要操作(存消息,取消息)的位置
item buff[n]; // 创建BUFF
semaphore mutex= 1, empty = n, full = 0; 
void producer(){
	do{
		产生一个消息并放到nextp里
		wait(empty); // 先检验是否为空
		wait(mutex); // 后检验是否互斥。顺序颠倒,在满的情况下,
					 // 会导致mutex无法释放,导致死锁
		buff[in] = nextp;
		in = (in+1)%n; // 让in指向下一个位置
		signal(mutex); // 释放互斥信号
		signal(full); // 放进去信息了,full+1
	}while(True)
}

void consumer(){
	do{
		wait(full);
		wait(mutex);
		nextc = buff[out];
		out = (out+1) mod n;
		signal(mutex);
		signal(empty);
		消费nextc中的产品
	}while(True)
}

void main(){
	cobegin
		producer();
		consumer();
	coend
}
		

注意:

  • 每个进程中 wait(mutex)和 signal(mutex)成对存在
  • 整个程序中 wait(empty/full)和 signal(empty/full)成对存在
  • wait()顺序不能颠倒,先资源再互斥,避免死锁

哲学家进餐问题

在这里插入图片描述

方法一:最多4人同时拿左筷子,最终保证一人能进餐

semaphore chopsticks[5] = {1,1,1,1,1} // 5根筷子
semaphore r = 4 // 最多4个人同时拿左筷子
void ohilosopher(int i)
{
	while(true){
		think();
		wait(r);// 看看有几个人拿了左筷子
		wait(chopsticks[i]); // 拿左筷子
		wait(chopsticks[(i+1)mod 5]; // 拿有筷子
		eat(); // 吃
		signal(chopsticks[(i+1)) mod 5]; //给出筷子
		signal(chopsticks[i]);// 给出筷子
		signal(r); // 1个吃完了,又允许1个人拿左筷子了
		think();
	}
}

方法二:同时给左右筷子

解法1:AND信号量

semaphore chopsticks[5] = {1,1,1,1,1}
void philosopher(int i){
	while(true){
		think();
		Swait(chopsticks [i] ; chopstick[i+1] mod 5); // 用AND信号量同时给左右筷子
		eat(); // 吃
		Ssignal(chopstick[(i+1) mod 5];chopstick[i]) // 吃完释放一双筷子
		think();
	}
}

解法2:信号量保护机制

semaphore mutex = 1
semaphore chopsticks[5] = {1,1,1,1,1}
void philosopher(int i){
	while(true){
		think();
		wait(mutex);
		wait(chopstick[i]);
		wait(chopstick[(i+1) mod 5]);
		signal(mutex);
		eat();
		signal(chopstick[i]);
		signal(chopstick[(i+1) mod 5]);
		think();
	}
}
		

方法三:让奇数先左后右,让偶数先右后左

在这里插入图片描述

semaphore chopsticks[5] = {1,1,1,1,1]
void philosopher(int i){
	while(true){
		if(i mod 2 == 0){
			wait(chopstick[(i+1) mod 5);
			wait(chopstick[i]);
			eat();
			signal(chopstick[i]);
			signal(chopstick[(i+1) mod 5]);
		}
		else{
			wait(chopstick[i]);
			wait(chopstick[(i+1) mod 5);
			eat();
			signal(chopstick[(i+1) mod 5]);
			signal(chopstick[i]);
		}
	}
}

读者–写者问题

在这里插入图片描述

分析

  • 写者和写者之间互斥,写者和读者之间互斥
  • 只要有一个读者,写者就不能去写

实现

int Readcount = 0; // 记录有几个读者在读
semaphore rmutex = 1; // 读写互斥 
semaphore wmutex = 1// 读者之间对Readcount访问互斥
void Reader(){
	do{
		wait(rmutex);
		if (Readcount == 0) // 判断是否是第一个读者
			wait(wmutex);
		Readcount++;
		signal(rmutex);
		read();
		wait(rmutex);
		Readcount--;
		if (Readcount == 0){ // 判断是否是最后一个读者
			signal(wmutex);
		signal(wmutex);
	}while(true)
}

void Writer(){
	while(true){
		wait(wmutex);
		写;
		signal(wmutex);
	}		

本文哲学家进餐问题参考【操作系统】“哲学家进餐”问题

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有理想、有本领、有担当的有志青年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值