Operating System-进程/线程内部通信-信号量、PV操作的实现和应用(解决哲学家进餐和生产者消费者问题)
本文主要内容:
- 信号量的实现
- 利用信号量解决哲学家用餐问题
- 利用信号量解决生产者消费者问题
一、信号量的实现
1.1 信号量结构
typedef struct
{
int value;
struct process * list
} semaphore;
value代表当前信号量可以使用的数量,list代表当前信号量上所等待的进程。
1.2 P操作实现
P(semaphore * s)
{
s.value--;
if(s.value < )
{
add current process to s.list;
block();
}
}
如果s.value<0。说明没有资源可用,当前进程加入list(等待进程列表),并且block当前进程。
1.3 V操作实现
V(semaphore * s)
{
s.value++;
if(s.value <= )
{
remove a process A from s.list;
wakeup(A);
}
}
s++代表释放了一个资源,如果s.value++后还是<=0。说明已经有至少一个进程在等待资源,这个时候就从list中拿出几个进程,wakeup这个进程,这样这个进程就可以开始使用这个刚刚被释放的资源了(这个进程不一定马上开始运行,至少是ready状态,什么时候运行取决于CPU的调度算法)。
1.4 忙等待问题
之前的Peterson的方案是通过忙等待来达到进程间的互斥访问的。PV操作其实也是无法避免的,PV操作的前提是不会有两个进程针对一个信号量在同时进行PV操作。这个时候信号量是信号量就是临界区域,如何让P和V操作对于信号量的操作互斥?
操作系统针对这个也是通过忙等待来完成的(一个进程对信号量进行操作的时候,其他进程一直等待)。不过把忙等待最终防止在信号量层面是最大限度的减少了忙等待的时间,因为pv操作的时间是非常快的。
二、利用信号量解决哲学家用餐问题
2.1 问题演示

五个哲学家,如上图所示:
- 每两个哲学家之间都有一只筷子,总共5只
- 哲学家都在思考,饿的时候就会拿起两边的筷子去吃饭
- 只有拿了两支筷子后才能开始吃饭
很明显,如果一个哲学家在想吃饭的时候如果其任何一个邻居在吃饭,他是没有办法吃饭的,筷子不够(要么只有一只筷子或者一只都没有)。
2.2 解决方案
void philosopher(i)
{
while(true)
{
P(chopstick[i]);
P(chopstick[( i + ) % ]);
eat();
V(chopstick[i]);
V(chopstick[( i + ) % ]);
think();
}
}
i代表第i个哲学家(0,1,2,3,4,5)。程序的核心思想就是利用PV操作让哲学家一直等待直到其左右两边的筷子都空闲再开始吃饭,吃完以后再把筷子放回去。
哲学家和筷子的编号

当哲学家0想用餐时,等待0,1筷子,哲学家2想用餐时等待2,3筷子。。
2.3 问题
上面的方案有个缺点:
当所有哲学家同时想用餐时,就会发生死锁,永远等待( starvation):

该问题下一篇博文专门介绍如何解决starvation。
三、利用信号量解决生产者消费者问题
之前的文章引入了生产者和消费者模式,但是该模式有有问题,wakeup有可能会丢失,其实核心问题还是因为对count(buffer容量)的访问没有做进程互斥访问,对buffer的访问没有做互斥访问,通过PV操作可以解决该问题
设置三个信号量:
- full,代表buffer中item的数量,默认为0
- empty代表buffer中空闲的数量,默认为buffer的容量n
- mutex,提供对于buffer的互斥操作,1代表可以访问buffer。0代表不可以访问buffer,初始值为1;
void producer()
{
while(true)
{
produce_item();
P(empty);//空闲容量-1,没有空闲容量,则等待,且进入block列表
P(mutex);//检测buffer是否可以访问
insert_item();
V(mutex);//释放buffer的访问权
V(full);//item数量+1,如果有consumer等待,则唤醒一个consumer
}
} void consumer()
{
while(true)
{
P(full);//item数量-1,如果没有item可以消费,则进入block列表
p(mutex);//检测buffer是否可以访问
remove_item();
V(mutex);//释放buffer访问权限
V(empty);//空闲容量+1,如果有producer等待吗,则唤醒一个producer
consume_item();
}
}
Operating System-进程/线程内部通信-信号量、PV操作的实现和应用(解决哲学家进餐和生产者消费者问题)的更多相关文章
- Operating System-进程/线程内部通信-信号量和PV操作
本文介绍操作系统进程管理的两个核心概念: 信号量 PV操作 一.信号量介绍 1.1 信号量引入 信号量(Semaphore)1965年由Dijkstra引入的.信号量一般由一个值是一个变量,其值有可能 ...
- InnoDB: Operating system error number 87 in a file operation. 错误87的解决方法
InnoDB: Operating system error number 87 in a file operation. 错误87的解决方法 140628 8:10:48 [Note] Plugi ...
- Operating System-进程/线程内部通信-管程(Monitor)介绍,实现以及应用
本文主要内容: 管程(Monitor)介绍 管程实现 管程应用 一.管程(Monitor)介绍 1.1 管程 前一篇文章介绍了信号量以及使用,信号量已经提供了一个方便且高效的进程同步机制,但是信号量有 ...
- linux下的信号量PV操作进阶之路
一.同步和互斥机制 信号量 互斥锁 同步:指多个任务按照约定的先后次序相互配合来完成一件事情. 比如读线程等待写线程写完之后再去读. 二.信号量-P/V操作 P(s)含义: if(信号量>0) ...
- java信号量PV操作 解决生产者-消费者问题
package test1; /** * 该例子演示生产者和消费者的问题(设只有一个缓存空间.一个消费者和一个生产者) * MySystem类定义了缓冲区个数以及信号量 * @author HYY * ...
- Linux下IPC中的信号量PV操作
代码如下所示,两边对照查看程序!(左图为先运行进程 右图为后运行进程) 运行的效果就是:当左边的进程检测到EOF,释放资源V操作之后,右边的进程会迅速的执行对应的printf的操作! 所有代码文 ...
- Operating System-进程/线程内部通信-竞争条件(Race Conditions)
从本文开始介绍进程间的通信,进程间通信遇到的问题以及方式其实和线程之间通信是一致的,所以进程间通信的所有理论知识都可以用在线程上,接下来的系列文章都会以进程之间的通信为模版进行介绍,本文主要内容: 进 ...
- Operating System-进程/线程内部通信-临界区(Critical Regions)
上一篇文章讲述了进程之间的竞争条件:多个进程同时进入一个共享区域,导致了数据的不一致,本文主要介绍如何解决这个问题. 一.临界区介绍 解决这个问题就是阻止多个进程同时进入这个共享区域,换句话说,进程之 ...
- Operating System:信号量
pv原语操作(1)操作系统PV意思:PV操作与信号量的处理相关,P表示通过的意度思,V表示释放的意思.(2)p操作和v操作是不可中断问的程序段,称为原语.如果将信号量看作共享变量,则pv操作为其临界区 ...
随机推荐
- Java中的HashMap
今天到中关村软件园面试被问到Java中HashMap的存值原理,瞬间无言已对,回答用了一个数组,然后沉默,面试官说,一次的面试失败不算什么,之后...... 1.关于hashCode hashCode ...
- 缩略图悬浮效果的jQuery焦点图
在线演示 本地下载
- Python内置标准模块
time 模块 1 >>> import time 2 >>> time.time() 3 1491064723.808669 4 >>> # t ...
- Asp.net 5 (MVC6) Areas 分区
1. Startup.cs 类的 Configure方法中, 加入Area路由设置代码: //app.UseMvcWithDefaultRoute(); app.UseMvc(routes=> ...
- 安装mysql5.7后无法启动,/var/run/mysqld 目录每次重启后都需要手动去创建--终极解决方案
鉴于很多童鞋反应,mysql5.7安装后出现无法启动,建立/var/run/mysqld 并赋权mysql用户解决了启动的问题,但是重启系统后又出现无法启动的问题,导致/var/run/mysqld ...
- EF Code-First 学习之旅 DataAnnotations
数据注解:配置选项的子集:Fluent API包含所有选项 System.ComponentModel.DataAnnotations Attributes: Attribute Descriptio ...
- poj 2478 Farey Sequence 欧拉函数前缀和
Farey Sequence Time Limit: 1000MS Memory Limit: 65536K Description The Farey Sequence Fn for ...
- enter回车---焦点切换
$(function(){ $('.enter').bind('keydown',function(e){ var inputs = $('.enter_cash'); var key = e.whi ...
- JavaScript数组和函数的使用
数组 数组:一个有顺序,有长度的数据集合 作用:存储大量数据 一.数组的定义 1.构造函数法:使用构造函数法的时候,都会使用new关键字 var arr=new Array(): 当长度为0 的时候, ...
- ControlTemplate,ItemsPanelTemplate,DataTemplate(wpf)
在WPF中有三大模板ControlTemplate,ItemsPanelTemplate,DataTemplate.其中ControlTemplate和ItemsPanelTemplate是控件模板, ...