持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
上篇我们讲了进程同步,但是只是这样的话是会出现问题的,会使大量的同步操作分散在各个进程中,为了减少这一现象,我们就要引入——
管程:为每个可共享资源设立一个专门的管程,来统一管理各个进程对该资源的访问。
还是先打地基,了解一下他的基本概念
管程的基本概念
定义
一个管程包含一个数据结构和能为并发进程所执行(在该操作系统上)的一组操作,这组操作能同步进程和改变管程中的数据。
三个部分
- 局部于管程的共享变量说明
- 对该数据结构进行操作的一组过程
- 对局部于管程的数据设置初始值的语句
语法
特点
- 局部数据变量只能被管程的过程访问,外部过程不可被访问
- 一个进程通过调用管程的一个过程进入管程
- 在任何时候都只能有一个进程在管程中执行,调用管程的任何其他进程都被挂起,等待管程变成可用的
那么说到这,我们又要引入一个比较很好的工具了
条件变量
它是管程内部的一种同步机制。每个条件变量都表示一种等待原因,对应着一个等待队列。(这里这个等待队列中存的就是因为这个等待原因而阻塞的PCB
他可以执行wait和signal操作,并且应该置于wait和signal之前,就比如:x.wait, x.signal
-
Wait()
- 将自己阻塞在等待队列中
- 唤醒一个等待者或释放管程的互斥访问
-
Signal()
- 将等待队列中的一个线程唤醒
- 如果等待队列为空,则等同空操作
掌握了基础概念,那我们书接上回,就可以用管程机制来解决一下生产者——消费者问题了。
利用管程解决生产者——消费者问题
步骤
- 建立管程PC
- put(item)过程放产品将生产的产品投放到缓冲池中,并用整型变量
count
来表示缓冲池中已有的产品数目,当count>=n
时,表示缓冲池已满,生产者需要等待 - get(item)过程取产品从缓冲池取走一个产品。当
count<=0
时,表示缓冲池空了,消费者需要等待。
Type PC = monitor
var in,out,count : integer;
buffer: array[0,...n-1] of item;
notfull,notempty : condition;//等待不满和等待不空
procedure entry put(item)
begin
if count>=n then notfull.wait;
buffer(in):=nextp;
in:=(in+1) mod n;
count:=count+1;
if notempty.queue then notempty.signal
end
Procedure entry get(item)
begin
if count<=0 then notempty.wait
nextc:=buffer(out);
out:=(out+1) mod n;
count:=count-1;
if notfull.queue then notfull.signal;
end
begin in:=out:=0;count:=0 end//初始化语句
以上这些代码都是系统准备好的,我们一看而过就好,下面时是调用进程的代码
两种管程
Hansen管程
主要用于真实OS和Java中
这里条件变量释放只是一个提示,我们还需要重新检查条件
Hoare管程
主要会在教材中见到他
这里条件变量释放的同时表示放弃管程访问