本文主要内容:

  • 信号量的实现
  • 利用信号量解决哲学家用餐问题
  • 利用信号量解决生产者消费者问题

一、信号量的实现

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操作的实现和应用(解决哲学家进餐和生产者消费者问题)的更多相关文章

  1. Operating System-进程/线程内部通信-信号量和PV操作

    本文介绍操作系统进程管理的两个核心概念: 信号量 PV操作 一.信号量介绍 1.1 信号量引入 信号量(Semaphore)1965年由Dijkstra引入的.信号量一般由一个值是一个变量,其值有可能 ...

  2. 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 ...

  3. Operating System-进程/线程内部通信-管程(Monitor)介绍,实现以及应用

    本文主要内容: 管程(Monitor)介绍 管程实现 管程应用 一.管程(Monitor)介绍 1.1 管程 前一篇文章介绍了信号量以及使用,信号量已经提供了一个方便且高效的进程同步机制,但是信号量有 ...

  4. linux下的信号量PV操作进阶之路

    一.同步和互斥机制 信号量 互斥锁 同步:指多个任务按照约定的先后次序相互配合来完成一件事情. 比如读线程等待写线程写完之后再去读. 二.信号量-P/V操作 P(s)含义: if(信号量>0) ...

  5. java信号量PV操作 解决生产者-消费者问题

    package test1; /** * 该例子演示生产者和消费者的问题(设只有一个缓存空间.一个消费者和一个生产者) * MySystem类定义了缓冲区个数以及信号量 * @author HYY * ...

  6. Linux下IPC中的信号量PV操作

    代码如下所示,两边对照查看程序!(左图为先运行进程 右图为后运行进程)    运行的效果就是:当左边的进程检测到EOF,释放资源V操作之后,右边的进程会迅速的执行对应的printf的操作! 所有代码文 ...

  7. Operating System-进程/线程内部通信-竞争条件(Race Conditions)

    从本文开始介绍进程间的通信,进程间通信遇到的问题以及方式其实和线程之间通信是一致的,所以进程间通信的所有理论知识都可以用在线程上,接下来的系列文章都会以进程之间的通信为模版进行介绍,本文主要内容: 进 ...

  8. Operating System-进程/线程内部通信-临界区(Critical Regions)

    上一篇文章讲述了进程之间的竞争条件:多个进程同时进入一个共享区域,导致了数据的不一致,本文主要介绍如何解决这个问题. 一.临界区介绍 解决这个问题就是阻止多个进程同时进入这个共享区域,换句话说,进程之 ...

  9. Operating System:信号量

    pv原语操作(1)操作系统PV意思:PV操作与信号量的处理相关,P表示通过的意度思,V表示释放的意思.(2)p操作和v操作是不可中断问的程序段,称为原语.如果将信号量看作共享变量,则pv操作为其临界区 ...

随机推荐

  1. 查看oracle当前连接数和进程数

    查询数据库当前进程的连接数: select count(*) from v$process; 查看数据库当前会话的连接数: select count(*) from v$session; 查看数据库的 ...

  2. php数组函数-array_rand()

    array_rand()函数返回数组中的一个随机键名,或者如果指定函数返回键名不止一个,则返 回一个包含随机键名的数组. array_rand(array,number); array:必需.规定数组 ...

  3. Cocos2d-x项目移植到WP8系列之五:播放MP3

    原文链接: http://www.cnblogs.com/zouzf/p/3972549.html 这一块的细节还是不太了解,只是东凑西拼能跑起来而已 1.网上下载lamb库 生成需要的lib库,详情 ...

  4. SwfUpload文件上传

    SWFUpload是一个flash和js相结合而成的文件上传插件,其功能非常强大.以前在项目中用过几次,但它的配置参数太多了,用过后就忘记怎么用了,到以后要用时又得到官网上看它的文档,真是太烦了.所以 ...

  5. Mysql中in语句排序

    这只是Mysql语句的写法,不同数据库写法不太一样, ,,,) order by instr('1,11115,11140,11135',id); 如果不使用order by,in语句查询出来的顺序是 ...

  6. P3391 文艺平衡树

    hh 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...

  7. 【arc101】比赛记录

    这场还好切出了D,rt应该能涨,然而这场的题有点毒瘤,700分的D没多少人切,更别说EF了.(暴打出题人)既然这样,干脆就水一篇博客,做个简单的比赛记录. C - Candles 这题是一道一眼题,花 ...

  8. java 类装载器原理

    问题引入:getClass().getClassLoader().getResource(path),各自代表什么意思? 解答:getClass():获得当前对象所属的Class对象 getClass ...

  9. Mac键盘图标与对应快捷按键标志汇总 分类

    Mac键盘图标与对应快捷按键 ⌘——Command () win键 ⌃ ——Control ctrl键 ⌥——Option (alt) ⇧——Shift ⇪——Caps Lock fn——功能键就是 ...

  10. JavaWeb -- 自定义标签实例, 防盗链, JSTL 核心标签

    1. 自定义标签应用实例1: 防盗链 标签处理类 public class RefererTag extends SimpleTagSupport { private String site; pri ...