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操作为其临界区 ...
随机推荐
- MyBatis SQL 生成方法 增删改查
此类根据JAVA实体BEAN生成MYBATIS的接口SQL(mapper) package com.sicdt.sicsign.bill.service.hessian; import java.la ...
- 【HackerRank】Find the Median(Partition找到数组中位数)
In the Quicksort challenges, you sorted an entire array. Sometimes, you just need specific informati ...
- 每日练习level-7
1.有序列表.无序列表.自定义列表如何使用?写个简单的例子.三者在语义上有什么区别?使用场景是什么? 能否嵌套? 有序列表是一列使用数字进行标记的项目,它使用<li>包含于<ol&g ...
- Windows下MarialDB使用
命令行控制启动和关闭:mysqld --console #这样启动ctrl+c即为关闭 启动:双击mysqld.exe即可 #此为后台启动 关闭:mysqladmin -uroot -pr ...
- 恢复性训练day1
DP: 0/1背包一个常见的错误是没有cmax(f[i][j],f[i-1][j]) 0/1背包的拓展中有转移式的变形,以及无限数量背包,分组背包等. 可化为背包问题的一般不会太难. 数组开小,出现大 ...
- linux系统怎么截图?linux系统中对指定区域进行截图的详细教程
windows系统的截图相当简单,方法也很多,但是linux下截图已经成为了一个老大难问题,在windows下用惯了qq截图,到了linux下没了qq,那要怎么办呢,prt sc sysrq 键全屏截 ...
- Ubuntu 12.04下安装OpenCV 2.4.2
http://sourceforge.net/projects/opencvlibrary/files/ Ubuntu 12.04下安装OpenCV 2.4.2 http://blog.csdn.ne ...
- Oracle、Mysql、SqlServer创建表和给表和字段加注释
一.Oracle --创建表 create table test ( id varchar2(200) primary key not null, sort number, ...
- Eclipse开发快捷键精选
1.alt+?或alt+/:自动补全代码或者提示代码2.ctrl+o:快速outline视图3.ctrl+shift+r:打开资源列表4.ctrl+shift+f:格式化代码5.ctrl+e:快速转换 ...
- idea ource 1.5 中不支持 switch 中存在字符串
报错内容如下: Error:(49, 20) java: -source 1.5 中不支持 switch 中存在字符串, (请使用 -source 7 或更高版本以允许 switch 中存在字符串) ...