Operating System-进程间互斥的问题-生产者&&消费者引入
之前介绍的几种解决进程间互斥的方案,不管是Peterson方案还是TSL指令的方式,都有一个特点:当一个进程被Block到临界区外面时,被Block的进程会一直处于忙等待的状态,这个不但浪费了CPU资源,还会有一个很坏的副作用。假设两个进程,H,L,H的优先级高,L进程的优先级非常低,CPU的调度规则是只要H处于Ready状态,则开始运行H,问题来了:
- H处于BLock状态,可能在等待外部资源
- L进入了临界区
- H处于Ready状态(外部资源满足),L还没有离开临界区
- 按照调度规则,CPU会Switch到H,L会挂起。
- H开始运行,但是由于L在临界区,这个时候H会处于无限循环,一直处于临界区外面等待。
- L也将永远无法离开临界区
一、生产者消费者引入
1.1 解决无限等待问题
如果一个进程不容许进入临界区时,这个时候让这个进程block,则解决了无线等待问题,文章开头提出的问题也就解决了。怎么block进程。
- 通过系统调用sleep,则可以让进程处于block状态。
- 被sleep的进程会一直挂起直到被调用wakeup
示意图:
生产者消费者主要是当往Buffer插入数据的时候发现buffer已经满了,则让生产者sleep,而是不无限循环等待
当发现buffer没有数据的时候让消费者sleep,而不是无限循环等待。
当buffer有数据时候,但是发现之前消费者属于sleep状态,则让消费者wakeup。
当buffer没有数据时候,但是发现之前生产者处于sleep状态,则让生产者wakeup。
1.2 代码演示
#definne N //buffer 的容量
int count = ; //buffer中item的数量 void producer(void)
{
int item;
while(true)//永远执行
{
item= produce_item();//生成下一个item
if(count == N)//如果buffer已经满了,则sleep
{
sleep();
}
insert_item(item);//将item放入buffer
count = count + ;//数量+1
if(count == )//之前buffer是空的,所以consumer处于sleep状态,现在有item了,唤醒consumer
{
wakeup(consumer);
}
}
} void consumer(void)
{
int item;
while(true)
{
if(count == )//如果buffer是空的,则sleep
{
sleep();
}
item = remove_item();//将item从buffer移除
count = count - ;//数量-1
if(count == N - )//之前buffer已经满了,所以producer处于sleep状态,现在移除了一个item,唤醒producer
{
wakeup(producer);
}
consume_item(item);//消费item
}
}
二、生产者消费者的条件竞争问题
上面的代码依然存在竞争条件问题(Race Conditions),考虑如下情况:
- buffer是空的,消费者刚刚读取到count,要去判断count是不是0,还没有走到sleep
- scheduler决定暂时停止消费者,让CPU去运行生产者
- 生产者如程序所示,会在buffer中增加一个item
- 因为之前count是你0,所以消费者认为consumer应该是sleep状态
- 发送wakeup(consumer)指令
以上完成后,由于之前的消费者因为cpu的调度没有走到sleep状态,所以wakeup对消费者是不起作用的。所以wakeup的信号就丢失了。
继续:
- cpu决定运行消费者,这个时候会从之前暂停的地方开始,count==0成立,consumer会进入sleep状态
- 接下来当生产者开始运行的时候,因为count已经是1了,所以永远都不会在运行wakeup(消费者)
最终结果:
- 生产者把buffer插满
- 消费者永远处于sleep状态
上面问题的关键是wakeup指令发给了一个没有sleep的进程,wakeup不起作用,wakeup的型号最终丢失了。
一个快速的解决方案是给进程加一个Wakeup waiting Bit,当一个wakeup请求发给一个处于wakeup的进程时,将这个进程的Wakeup waiting Bit标志位设置为true。接下来当有sleep给这个进程时,判断一下如果Wakeup waiting Bit为true,则不sleep。
这个方法能暂时解决问题,但是很糟糕,如果有多个进程时,就需要很多标志位。接下来几篇文章会专门将信号量,互斥体等来解决生产者消费者的竞争条件问题。
Operating System-进程间互斥的问题-生产者&&消费者引入的更多相关文章
- Operating System-进程间互斥的方案-保证同一时间只有一个进程进入临界区(3)- TSL指令
本文接上一篇文章继续介绍如何实现同一时间只允许一个进程进入临界区的机制.本文主要介绍TSL指令. 方案汇总 屏蔽中断 锁变量 严格轮换法 TSL指令 Peterson解法 一.What is TSL ...
- pthread mutex 进程间互斥锁实例
共享标志 定义 名称 描述 0 PTHREAD_PROCESS_PRIVATE 进程内互斥锁 仅可当前进程内共享 1 PTHREAD_PROCESS_SHARED 进程间互斥锁 多个进程间共享 第一个 ...
- POSIX信号量与互斥锁实现生产者消费者模型
posix信号量 Link with -lpthread. sem_t *sem_open(const char *name, int oflag);//打开POSIX信号量 sem_t *sem_o ...
- python并发编程之守护进程、互斥锁以及生产者和消费者模型
一.守护进程 主进程创建守护进程 守护进程其实就是'子进程' 一.守护进程内无法在开启子进程,否则会报错二.进程之间代码是相互独立的,主进程代码运行完毕,守护进程也会随机结束 守护进程简单实例: fr ...
- Mutex 进程间互斥
学习Mutex的心得,不一定对,先记录一下. 同步技术分为两大类,锁定和信号同步. 锁定分为:Lock.Monitor 信号同步分为:AutoResetEvent.ManualResetEvent.S ...
- Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题
Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...
- posix 匿名信号量与互斥锁 示例生产者--消费者问题
一.posix 信号量 信号量的概念参见这里.前面也讲过system v 信号量,现在来说说posix 信号量. system v 信号量只能用于进程间同步,而posix 信号量除了可以进程间同步,还 ...
- 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)
参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...
- 网络编程基础----并发编程 ---守护进程----同步锁 lock-----IPC机制----生产者消费者模型
1 守护进程: 主进程 创建 守护进程 辅助主进程的运行 设置进程的 daemon属性 p1.daemon=True 1 守护进程会在主进程代码执行结束后就终止: 2 守护进程内无法再开启子进程 ...
随机推荐
- 【Topcoder】SRM157 DIV2总结
250分题:简单的二分,就是平常玩的猜数字游戏 代码:GitHub 500分题:给出一个员工一天的打卡时间段,要求求出员工这一天的工资.其中正常上班时间是6:00:00到18:00:00,薪水是wag ...
- Wi-Fi基带芯片和Wi-Fi无线网卡设计方案
转:http://wenku.baidu.com/link?url=Q0ImC 0IIG7qrbB8DpGrrU3aOYvxNYCyHsxukspH8XMCDYMjYMPSJq_TCISC5amsNY ...
- Python编程-面向对象和类
一.面向对象的程序设计 1.面向过程 VS 面向对象 (1)编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程,一个程序是程序员为了得到一个任务结果而编写的一组 ...
- Shell编程之循环控制及状态返回值
1.break.continue.exit.return的对比 break.continue在条件语句和循环语句中用于控制程序走向: exit用于终止所有语句并退出当前脚本,还可以返回上一次程序或命令 ...
- django大全
数据库配置: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbname', 'USER': 'ro ...
- Android系统--Binder系统具体框架分析(一)补充
Android系统--Binder系统具体框架分析(一)补充 补充:对Binder驱动分析一的代码补充,添加saygoobye和saygoodbye_to服务 test_server.h #ifnde ...
- echache缓存的简单使用方法
1.需要echache的jar包 2.需要配置文件ehcache.xml和ehcache.xsd,主要是在ehcache.xml中进行配置 3.修改配置文件ehcache.xml ,例如添加配置如下 ...
- Start and Use the Database Engine Tuning Advisor
https://docs.microsoft.com/en-us/sql/relational-databases/performance/start-and-use-the-database-eng ...
- 【P2016】战略游戏(贪心||树状DP)
这个题真是...看了一会之后,发现有一丝丝的熟悉,再仔细看了看,R,这不是那个将军令么...然后果断调出来那个题,还真是,而且貌似还是简化版的...于是就直接改了改建树和输入输出直接交了..阿勒,就2 ...
- 描述一下你最常用的编程风格---JAVA
描述一下你最常用的编程风格---JAVA 描述一下你最常用的编程风格---JAVA (1)类名首字母应该大写.字段.方法以及对象(句柄)的首字母应小写.对于所有标识符,其中包含的所有单词都 ...