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 守护进程内无法再开启子进程 ...
随机推荐
- 建议41:使用argparse处理命令行参数
# -*- coding:utf-8 -*- ''' 以现阶段最好用的参数处理标准库是argparse ''' import argparse parser = argparse.ArgumentPa ...
- OpenGL纹理上下颠倒翻转的三种解决办法
http://blog.csdn.net/narutojzm1/article/details/51940817 综述 在使用OpenGL函数加载纹理到图形时,经常遇到纹理上下颠倒的问题.原因是因为O ...
- python之json模块的基本使用
json模块的作用:将字符串和字典相互转换 json和eval的区别: eval函数不能识别null转换成None json可以将null转换成python可以识别的None json序列化和反序列化 ...
- Eclipse开发快捷键精选
1.alt+?或alt+/:自动补全代码或者提示代码2.ctrl+o:快速outline视图3.ctrl+shift+r:打开资源列表4.ctrl+shift+f:格式化代码5.ctrl+e:快速转换 ...
- maven 安装、运行、获取帮助 —— maven权威指南学习笔记(二)
这部分在网上很容易找到详细教程,这里就略写了. 基础:系统有配置好的jdk,通过 命令行 java -version,有类似下面的提示,表示java环境以配好 下载maven:官网 http://ma ...
- Centos6.5下ElasticSearch1.4.4的安装
1.下载ElasticSearch 官网地址 https://www.elastic.co/ 2.安装elasticsearch-1.4.4.tar.gz tar -zxvf elasticsearc ...
- java.lang.NullPointerException报错的几种情况
java.lang.NullPointerException报错的几种情况: 1.字符串变量未初始化: 2.接口类型的对象没有用具体的类初始化,比如: List stuList :这种情况就会报空指针 ...
- web容器调用Filter和Servlet顺序学习
web容器调用Filter和Servlet顺序学习 一直对Filter和Servlet在哪里被web容器调用迷惑,后查看tomcat源码,揭开了其面纱.1. 下面是一个简单的时序图: 2. 对上 ...
- codevs1907 方格取数 3
«问题描述:在一个有m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.«编程任务:对于给定的方格棋 ...
- bzoj 2656 [Zjoi2012]数列(sequence) 递推+高精度
2656: [Zjoi2012]数列(sequence) Time Limit: 2 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Descri ...