浅谈操作系统——管程机制

571 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

上篇我们讲了进程同步,但是只是这样的话是会出现问题的,会使大量的同步操作分散在各个进程中,为了减少这一现象,我们就要引入——

管程:为每个可共享资源设立一个专门的管程,来统一管理各个进程对该资源的访问。

还是先打地基,了解一下他的基本概念

管程的基本概念

定义

一个管程包含一个数据结构和能为并发进程所执行(在该操作系统上)的一组操作,这组操作能同步进程和改变管程中的数据。

三个部分

  • 局部于管程的共享变量说明
  • 对该数据结构进行操作的一组过程
  • 对局部于管程的数据设置初始值的语句

语法

image.png

特点

  • 局部数据变量只能被管程的过程访问,外部过程不可被访问
  • 一个进程通过调用管程的一个过程进入管程
  • 在任何时候都只能有一个进程在管程中执行,调用管程的任何其他进程都被挂起,等待管程变成可用的

那么说到这,我们又要引入一个比较很好的工具了

条件变量

它是管程内部的一种同步机制。每个条件变量都表示一种等待原因,对应着一个等待队列。(这里这个等待队列中存的就是因为这个等待原因而阻塞的PCB

他可以执行wait和signal操作,并且应该置于wait和signal之前,就比如:x.wait, x.signal

  • Wait()

    • 将自己阻塞在等待队列中
    • 唤醒一个等待者或释放管程的互斥访问
  • Signal()

    • 将等待队列中的一个线程唤醒
    • 如果等待队列为空,则等同空操作

掌握了基础概念,那我们书接上回,就可以用管程机制来解决一下生产者——消费者问题了。

利用管程解决生产者——消费者问题

步骤

  1. 建立管程PC
  2. put(item)过程放产品将生产的产品投放到缓冲池中,并用整型变量count来表示缓冲池中已有的产品数目,当count>=n时,表示缓冲池已满,生产者需要等待
  3. 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//初始化语句

以上这些代码都是系统准备好的,我们一看而过就好,下面时是调用进程的代码

image.png

两种管程

Hansen管程

主要用于真实OS和Java中

image.png

这里条件变量释放只是一个提示,我们还需要重新检查条件

Hoare管程

主要会在教材中见到他

image.png

这里条件变量释放的同时表示放弃管程访问