本文主要内容:

  • 管程(Monitor)介绍
  • 管程实现
  • 管程应用

一、管程(Monitor)介绍

1.1 管程

前一篇文章介绍了信号量以及使用,信号量已经提供了一个方便且高效的进程同步机制,但是信号量有个缺点就是每次都需要程序员专门的去调用PV操作,如果程序员由于大意调用错了PV操作,比如该调用P操作的时候却调用了V操作,该针对X信号量调用P操作,却对Y信号量调用了P操作。这种错误是非常危险的,因为进程同步的问题不是每次都能重现,比如前面的错误在测试环境可能不会出现错误,但是到了生产环境就有可能出现,且无法重现。

为了解决上述问题,引入了管程(Monitor),信号量是操作系统层面的结构,管程是一个程序结构,由编程语言封装,最终由编译器:

  • 一个管程定义了一个数据结构和能够并发进程所执行的一组操作,这组操作能同步进程和改变管程中的数据
  • 进程可以调用管程的操作,但是不能访问管程的内部数据结构
  • 它表示一个对象自己维护自己的状态,并且能够根据自身状态来同步并发的线程操作,而不是把这种同步的手段交给调用者来处理。
  • 管程保证同一时间只有一个进程处在管程内部的方法内
monitor MonitorName
{
//shared variable declarations
procedure P1(...)
{ }
procedure P2(...)
{ } procedure P3(...)
{ } procedure PN(...)
{ } initialization code(...)
{ }
}

1.2 条件(Condition variables)

只有管程是不够的,在生产者消费者的例子中,当发现buffer中如果已经没有item的时候,消费者如何block自己呢?介于这个原因,又引入了条件变量(Condition Variables)。条件变量同时提供了两个方法:P以及V用于block和unblock。

二、管程实现

管程通过队列来跟踪那些尝试着想访问管程的进程,为了排他访问,管程必须得有一个锁,访问管程的进程会得到这个锁,其他尝试访问管程的进程就得block。被block的进程会被放入队列,等待被unblock。

管程的实现中有如下的队列:

  1. 进入队列(Entry Queue),保存尝试从外部访问管程程序的进程,每个管程至少有一个进入队列
  2. 被唤醒的队列(Signaller Queue),保存刚刚执行了V操场的进程(signal)
  3. 等待队列(Waiting Queue),保存刚刚被V操作唤醒的进程
  4. 条件变量队列(Condition Variable Queue),保存刚刚执行了条件变量Wait(P)操作的进程

三、管程应用

上一篇文章针对哲学家用餐给出的解决方案有个问题:当所有哲学家同时拿起筷子想吃饭的时候就会发生死锁,所有哲学家都会一直处于等待状态。本文用管程给出了解决方案,哲学家吃饭得满足的条件:

  1. 哲学家饿(hungry)
  2. 哲学家的左右邻居都没有吃饭

如果满足上面条件,则哲学家便可以拿起筷子进行用餐,否则哲学家就得等待

monitor dp
{
enum {thinking, hungry, eating} state[];
condition self[]; void pickup(int i) {
state[i] = hungry;
test(i);
if (state[i] != eating)
self[i].wait();//P操作
} void putdown(int i) {
state[i] = thinking;
test( (i+)% );
test( (i+)% );
} void test(int i) {
if ((state[(i+)%] != eating) &&
(state[i] == hungry) &&
(state[(i+)%] != eating)) {
state[i] = eating;
self[i].signal();//V操作
}
} void init() {
for (int i = ; i < ; i++)
state[i] = thinking;
}
}

Condition Self代表五个哲学家,当不能吃时候进行wait。

db.pickup(i);//找筷子
...
eating//吃
...
dp.putdown(i);//放下筷子

管程更多的是对资源的并发访问做了一次封装,感觉有很多OO编程的思想,直接用信号量的话,各种控制会很发散,当然容易出错,信号量本事是没有问题的。但是使用容易出错。且由于散发在多出,出问题不好排查,也不好修复。

管程是一种编程思想,这种思想就是封装,并且有DRY的感觉。

Operating System-进程/线程内部通信-管程(Monitor)介绍,实现以及应用的更多相关文章

  1. 突破python缺陷,实现几种自定义线程池 以及进程、线程、协程的介绍

    Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. #!/usr/bin/env python # -*- coding:utf-8 -*- import t ...

  2. python进程.线程和协程的总结

    I.进程: II.多线程threading总结 threading用于提供线程相关的操作,线程是应用系统中工作的最小单位(cpu调用的最小单位). Python当前版本的多线程没有实现优先级,线程组, ...

  3. python系列7进程线程和协程

    目录 进程 线程 协程  上下文切换 前言:线程和进程的关系图 由下图可知,在每个应用程序执行的过程中,都会去产生一个主进程和主线程来完成工作,当我们需要并发的执行的时候,就会通过主进程去生成一系列的 ...

  4. Python 进程、线程、协程的介绍与使用

    一.必备的理论基础 二.操作系统发展史 三.进程理论 四.线程理论 五.协程 一.必备的理论基础 操作系统理论: 操作系统是一个协调\管理\控制计算机硬件资源与应用软件资源的控制程序 操作系统的两大功 ...

  5. 进程线程协程补充、docker-compose一键部署项目、搭建代理池、requests超时设置、认证设置、异常处理、上传文件

    今日内容概要 补充:进程,线程,协程 docker-compose一键部署演示 搭建代理池 requests超时设置 requests认证设置 requests异常处理 requests上传文件 内容 ...

  6. Linux查看进程线程个数

    1.根据进程号进行查询: # pstree -p 进程号 # top -Hp 进程号 2.根据进程名字进行查询: # pstree -p `ps -e | grep server | awk '{pr ...

  7. Python之路第一课Day9--随堂笔记之二(进程、线程、协程篇)

    本节内容 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queu ...

  8. Python之路,Day9, 进程、线程、协程篇

    本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者 ...

  9. Python学习之路--进程,线程,协程

    进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Q ...

随机推荐

  1. python中初始化实例属性

    虽然我们可以自由地给一个实例绑定各种属性,但是,现实世界中,一种类型的实例应该拥有相同名字的属性.例如,Person类应该在创建的时候就拥有 name.gender 和 birth 属性,怎么办? 在 ...

  2. python之使用__future__(解决版本不同,不兼容问题)

    Python的新版本会引入新的功能,但是,实际上这些功能在上一个老版本中就已经存在了.要“试用”某一新的特性,就可以通过导入__future__模块的某些功能来实现. 例如,Python 2.7的整数 ...

  3. iOS面试必备-iOS基础知识

    近期为准备找工作面试,在网络上搜集了这些题,以备面试之用. 插一条广告:本人求职,2016级应届毕业生,有开发经验.可独立开发,低薪求职.QQ:895193543 1.简述OC中内存管理机制. 答:内 ...

  4. LeetCode——Construct Binary Tree from Preorder and Inorder Traversal

    Question Given preorder and inorder traversal of a tree, construct the binary tree. Note: You may as ...

  5. 创建表空间及用户的SQL

    --创建表SOFA空间: CREATE SMALLFILE TABLESPACE "SOFA" DATAFILE 'G:\oracle\product\10.2.0\ORADATA ...

  6. windows 10系统更新失败的解决办法

    最近遇到一个问题,系统总是自动下载一个更新,看样子是个补丁吧,但是每次提醒重新启动以安装更新,但每次又安装失败,回退.就这样,下载,重启,安装失败,下载......一直循环,搞得都不敢关机了,因为这样 ...

  7. xenapi-add-support-for-vgpu

    Model types 为了在vm中支持vgpu,问题在于vgpu是否应该被当作一个PCI设备, 虽然物理GPU不是一个SR-IOV设备,但vgpu却是以一个类似SR-IOV device上的VF赋给 ...

  8. Tensorflow中的命名空间scope

    1.name_scope 在tensorflow中有两种声明变量的方式,tf.get_variable()和tf.Variable(). name_scope对于tf.get_variable()无效 ...

  9. 在线显示office文件

    微信或手机浏览器在线显示office文件 1.判断浏览器类型 HttpServletRequest req = ServletActionContext.getRequest(); String us ...

  10. Sublime Text 3总是出现“1 missing dependency was just installed.”

    Sublime Text 3总是出现“1 missing dependency was just installed.” 原因及结果 https://github.com/wbond/package_ ...