1. 生产者—消费者问题

利用记录型信号量解决生产者—消费者问题

这类问题就是两个进程对一个临界资源的使用的具体例子

假定在生产者和消费者之间的共用缓冲池(就像是仓库),共有n个缓冲区(n个位置)。缓冲池未满生产者可以将消息放入缓冲池;缓冲池不为空消费者可以将消息取走。

可以利用互斥信号量mutex实现对缓冲池的互斥使用。

利用记录型信号量empty和full分别标识缓冲池中空的缓冲区和满的缓冲区。

可见:

①生产者和消费者对于仓库counter的使用是互斥的(竞争)。

②而生产者和消费者之间又相互制约(协作)。就是必须生产者生产了消费者才可以使用,反之.

解决方法:

设置互斥信号量M实现两个进程对缓冲池的互斥使用。

设置资源信号量E和F表示缓冲池中空的缓冲区和满的缓冲区数量。

初始值M=1,E=n,F=0。(表示刚开始缓冲池中缓冲区全为空)

对于生产者来说,首先要P(E),若是E为0,表示空的缓存区数量为0,则进入阻塞,必须等待消费者消费才能进入。

对于消费者来说,首先要P(F),若是F为0,表示满的缓存区数量为0,则进入阻塞,必须等待生产者生产才能进入。

同时,二者P(E/F)通过后,无论是谁先进入P(M),另一个都得阻塞。实现了对缓冲池的互斥使用。

注意:

互斥使用时,P(M)和V(M)在同一个进程内成对使用。

而协作使用,P(E/F)和V(E/F)分别在互相协作的两对进程内成对使用。

2. 哲学家进餐问题

这类问题是多个进程对多个临界资源的使用的实例。

可知,筷子是临界资源,在同一时间内只能一个人使用。

为了实现对筷子的互斥使用,可以用一个信号量表示一个筷子,由五个信号量构成信号量数组:

Var chopstick: array[0,…,4] of semaphore;信号量数组,表示五双筷子。

所有信号量均被初始化为1那么,第i位哲学家的活动可描述为:

repeat

wait(chopstick[i]);                         等待第i个筷子,即左边筷子        P(i)

wait(chopstick[(i+1)mod 5]);        等待第i+1个筷子,即右边筷子        P(i+1)

eat;                                               吃饭,使用临界资源

signal(chopstick[i]);                       释放第i个筷子,即左边筷子        V(i)

signal(chopstick[(i+1)mod 5]);      释放第i+1个筷子,即右边筷子        V(i+1)

think;                                             思考

until false;

当哲学家饥饿时,总是先去拿他左边的筷子,即执行wait(chopstick[i]); 成功后,再去拿他右边的筷子,即执行 wait(chopstick[(i+1)mod 5]);又成功后便可进餐。进餐完毕,又先放下他左边的筷子,然后再放右边的筷子。

这样虽然不会出现两个哲学家同时吃饭,但是可能会引起死锁:

假如五位哲学家同时饥饿而各自拿起左边的筷子时,就会使五个信号量chopstick 均为0; 当他们再试图去拿右边的筷子时,都将因无筷子可拿而无限期地等待。

解决方法

①至多只允许四位哲学家同时拿左边的筷子,即至少保证有一位哲学家可以吃饭,在他吃完之后释放两双筷子,使得其他哲学家也可以吃饭。

②仅当哲学家左右两双筷子都空闲,才允许拿起筷子吃饭。即AND型信号量。

③规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子, 而偶数号哲学家则相反。按此规定,将是1、2号哲学家竞争1号筷子; 3、4号哲学家竞争3号筷子。即五位哲学家都先竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一位哲学家能获得两只筷子而进餐。

方法③实现起来很复杂,且不实用。

方法①即使用记录型信号量解决哲学家进餐问题:

方法②即使用AND信号量解决哲学家进餐问题:

(1)利用记录型信号量解决哲学家进餐问题

5支筷子是临界资源,用5个信号量表示S[5],所有信号量初始化为1, 表示一开始所有筷子可用;

设置记录型信号量N表示允许同时进餐人数,其初始值为4,那么第i个哲学家(i=0,1,...,4)的过程可以表示为:

定义信号量: N=4,S[5]={1,1,1,1,1}

while( 1 ) {

P( N )

P( S[i] )         // 拿左边的筷子

P( S[(i+1)%5] ) // 拿右边的筷子

进餐...

V( S[i] ) // 释放左边筷子

V( S[(i+1)%5] ) // 释放右边筷子

V( N )

思考...

}

相较于开始时出现死锁的解决方法,这里添加了一个记录型信号量N,放在最开始,当N等于0表示已经有4个哲学家拿起了左边筷子,第五个哲学家就得阻塞,等待有哲学家吃完,释放N。

(2)利用AND信号量机制解决哲学家进餐问题

Var chopsiick array of semaphore:=(1,1,1,1,1);

processi

repeat

think;                                                                思考

Sswait(chopstick[(i+1)mod 5],chopstick[i]);   等待左右两双筷子

eat;                                                                   吃

Ssignat(chopstick[(i+1)mod 5],chopstick[i]);  释放左右两双筷子

until false;

3. 读者写者问题

这类问题是一个临界资源被两类进程使用,这两类之间互斥,但是每一类自身不互斥使用的实例。

读者/写者问题的关键:

多个读者进程可以共存

一个写进程和其他读/写进程不能共存

读者/写者问题的实例:

数据库

ftp 服务器

......
利用信号量解决读者—写者问题

为实现Reader与Writer进程间在读或写时的互斥而设置了一个互斥信号量w。

再设置一个整型变量n表示正在读的进程数目。

由于只要有一个Reader进程在读,便不允许Writer进程去写。因此,仅当n=0,表示尚无Reader进程在读时,Reader进程才需要执行 P(w)操作。

若P(w)操作成功,Reader进程便可去读,相应地,做Readcount+1操作。

仅当Reader进程在执行了Readcount减1操作后其值为0时,才须执行V(w)操作,以便让Writer进程写。

又因为 n 是一个可被多个Reader进程访问的临界资源,因此,也应该为它设置一个互斥信号量 s 。

信号量定义

W=1, S=1        //W用来让读者进程和写者进程互斥访问临界资源,S用来让读者进程之间互斥访问临界资源正在读的读者数量 n。

整形变量 n=0 // 记录读者进程数量

读者进程:                                                                写进程:

P( S )                                                                        P( W )

if( n==0 )                                                                写操作

p( W )                                                        V( W )

n = n+1

V( S )

执行读操作

P( S )

n = n-1

if( n==0 )

V( W )

V( S )

可知,当读者进程运行时,首先应P(S),互斥访问临界资源 n ,且仅当n=0时,进行P(W),表示读者数量不为0了,此时写者进程只能阻塞,然后V(S),允许其他读者进程进入并修改临界资源n。

4. 理发师问题

这个问题是生产者/消费者,读者/写者问题的混合是一个综合问题

理发师问题描述如下

角色有两个,理发师和顾客。

只有一个理发师和一把理发椅子,另有N把椅子供顾客休息等待。

没有顾客时,理发师休息,等待顾客。

每个顾客来时,先看是否有椅子空位,有空位,坐下等待;否则不等待直接走。

信号量定义:

X=0 Y=0 X用来表示理发师是否休息,Y表理发师是否正在理发

S=1 访问临界资源count

等待顾客数:

int count;

注意:

理发师是一个循环

而顾客是多个,但每一个只执行一次,不循环

关于count--,也可以考虑放入顾客进程中

5. 管程机制

系统中的各种硬件资源和软件资源,均可用数据结构抽象地描述其资源特性,即用少量信息和对该资源所执行的操作来表征该资源,而忽略了它们的内部结构和实现细节。

利用共享数据结构抽象地表示系统中的共享资源,而把对该共享数据结构实施的操作定义为一组过程,如资源的请求和释放过程request和 release。

进程对共享资源的申请、释放和其它操作,都是通过这组过程对共享数据结构的操作来实现的,这组过程还可以根据资源的情况,或接受或阻塞进程的访问,确保每次仅有一个进程使用临界资源,这样就可以统一管理对共享资源的所有访问,实现进程互斥。

代表共享资源的数据结构,以及由对该共享数据结构实施操作的一组过程所组成的资源管理程序,共同构成了一个操作系统的资源管理模块,我们称之为管程。

管程被请求和释放资源的进程所调用。 Hansan为管程所下的定义是:“一个管程定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作,这组操作能同步进程和改变管程中的数据” 。

管程由四部分组成:

①管程的名称

②局部于管程内部的共享数据结构说明

③对该数据结构进行操作的一组过程

④对局部于管程内部的共享数据设置初始值的语句

例如:

如果用管程来管理筷子,那么哲学家进餐问题就可以简单的写为:

dp.pickup(i);    申请第i位置吃饭(该位置的两个筷子)

eat

dp.putdown(i);

think

这也是目前大多数系统中,对系统资源的一种处理方式,有系统统一处理资源使用者的同步问题。

6. Windows 提供的同步操作(或者信号量机制)

包括两类:

①API 方式

除前面介绍过的“临界区”变量,还提供下面 4 种同步对象:

Type         Description

Event         事件

Mutex         互斥量

Semaphore         信号量

Waitable timer         专门时钟

然后需要专门的 Wait 函数来实现以上同步对象的操作。

API 方式在实际使用中比较麻烦,建议使用 MFC 方式。

②MFC 形式

包括以下四个同步类对象:

1) CSemaphore

2) CMutex

3) CCriticalSection

4) CEvent

以及两个操作这些同步对象的类:

1) CSingleLock //

2) CMultiLock // 实现 AND 操作

二、进程管理(4.经典进程同步问题)相关推荐

  1. 操作系统实验一 Linux基本操作|实验二 进程管理

    由于当时没存代码,只有实验文档代码截图,文末也可直接获取实验文档. 操作系统实验 目录 实验一 Linux基本操作 实验二进程管理 实验一 Linux基本操作 1实验目的 1.熟悉在Linux操作系统 ...

  2. 操作系统实验二 进程管理

    进程管理 一.实验目的 1. 理解进程的概念,明确进程和程序的区别. 2. 理解并发执行的实质. 3. 掌握进程的创建.睡眠.撤销等进程控制方法. 二.实验内容与基本要求 用C语言编写程序,模拟实现创 ...

  3. 【操作系统实验】实验二 进程管理

    进程管理 实验2-1 使用fork创建进程 代码 实验2-2 使用exec替换子进程程序 代码 实验2-3 分析进程的父进程 代码 实验2-4 共享存储区机制进程通信 代码 实验2-5 消息队列实现进 ...

  4. linux内核笔记二 进程管理

    三.系统的进程管理 1.系统的进程运转方式 系统时间 (jiffies 系统滴答) cpu内部有一个RTC(系统的定时器),会在上电的时候调用mktime函数算出1970年一月一日0时开始到当前开机点 ...

  5. 操作系统——实验二 进程管理

    1.实验目的 (1)加深对进程概念的理解,明确进程和程序的区别. (2)进一步认识并发执行的实质. (3)分析进程竞争资源现象,学习解决进程互斥的方法. 2.实验预备内容 (1)阅读Linux的sch ...

  6. 计算机操作系统实验二 进程管理

    一.实验目的 1.掌握进程的概念,明确进程的含义 2.认识并了解并发执行的实质 二.实验内容 1.编写一段程序,使用系统调用fork( )创建两个子进程.当此程序运行时,在系统中有一个父进程和两个子进 ...

  7. OS知识点汇总(考研用)——第二章:进程管理(下)

    OS知识点汇总(考研用)--第二章:进程管理(下)  本文参考于<2021年操作系统考研复习指导>(王道考研),<计算机操作系统教程> 思维导图: 文章目录 OS知识点汇总(考 ...

  8. Linux 进程管理学习笔记(一)

    一 内核空间和用户空间 内核:操作系统(OS)中最核心的部分,负责管理和分配硬件资源.主要由进程管理和调度,内存管理,文件系统和IO等几个主要部分组成. 内核子系统只工作在内核空间(kernel-sp ...

  9. 操作系统-进程管理实验(2)

    实验二  进程管理 一.目的 本课题实验的目的是,加深对进程概念及进程管理各个部分内容的理解:熟悉进程管理中主要数据结构的设计及进程调度算法,进程控制机构,同步机构,通信机构的实施. 二.题目 进程管 ...

最新文章

  1. iShow UI for React 最佳实践
  2. apache部署https
  3. 【多题合集】线段覆盖1、2、3
  4. Spark源码分析之Master主备切换机制
  5. 零基础学启发式算法(4)-模拟退火 (Simulated Annealing)
  6. 构造一个简单的linux系统
  7. spring 从源码学设计1-doDispatch()
  8. 【Android_CN_OAID】安卓设备唯一标识解决方案,可作为移动安全联盟统一 SDK (miit_mdid_xxx.aar)的替代方案。
  9. Silvaco TCAD仿真2——Silvaco TCAD 档名
  10. Nacos注册中心8-Server端(处理注册请求)
  11. Go 学习笔记 Go 第三方库之 viper(解析配置文件、热更新配置文件)
  12. 2022-2027年中国建筑施工机械租赁市场规模预测及投资战略咨询报告
  13. macbook linux 双系统,macbookair双系统怎么切换使用?macbookair双系统切换使用的方法...
  14. 【动态规划】买卖股票
  15. 启动vue项目出现的错误合集
  16. 扩大eclipse的运行内存
  17. 【转】英文论文审稿意见汇总
  18. obj-y,obj-m 区别
  19. dwz打开自定义dialog
  20. 用爬虫玩转石墨文档API

热门文章

  1. KEIL MDK RTX 实时操作系统
  2. python从邮箱获取指定邮件_用python提取并统计指定邮箱里的特定邮件 | 学步园
  3. 华为Freelace pro音质突然下降的解决方案
  4. ArcGIS JS 版军事标绘图、燕尾箭头;支持VUE版本
  5. U盘启动如何进入pe
  6. w ndows 10关机,Win10设置定时开关机休眠唤醒的方法
  7. shopee跨境店铺怎么申请入驻-跨境知道
  8. 网上宣传的0月租流量卡是骗局吗?看完你就知道了!
  9. 3.矩阵乘法和逆矩阵
  10. lightning接口linux驱动,iPhone 8惊喜曝光:Lightning接口换USB Type-C