本文主要内容:

  • 管程(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. 【leetcode刷提笔记】Search Insert Position

    Given a sorted array and a target value, return the index if the target is found. If not, return the ...

  2. ES6 随记(3.1)-- 字符串的拓展

    上一章请见: 1. ES6 随记(1)-- let 与 const 2. ES6 随记(2)-- 解构赋值 4. 拓展 a. 字符串的拓展 有些字符需要 4 个字节储存,比如 \uD83D\uDE80 ...

  3. Ubuntu 12.04下boost库的交叉编译

    oost Ver: 1.55.0Compiler : GNU gcc 4.6 for ARM 1. 确保ARM编译成功安装,并配置好环境变量.2. 解压boost压缩包 3. 进入目录执行./boot ...

  4. Linux的压缩命令(tar,gzip,zip)

    打包和压缩.打包是指将一大堆文件或目录变成一个总的文件:压缩则是将一个大的文件通过一些压缩算法变成一个小文件. 这源于Linux中很多压缩程序只能针对一个文件进行压缩,这样当你想要压缩一大堆文件时,你 ...

  5. Whitewidow:SQL 漏洞自动扫描工具

    Whitewidow 是一个开源的 SQL 漏洞自动扫描器,可用通过文件列表运行,或者从 Google 爬取并发现有潜在漏洞的网站. 这个工具支持自动格式化文件.随机用户代理.IP 地址.服务器信息. ...

  6. WebUploader API文档

    Web Uploader内部类的详细说明,以下提及的功能类,都可以在WebUploader这个变量中访问到. As you know, Web Uploader的每个文件都是用过AMD规范中的defi ...

  7. 未能将网站配置为使用ASP.NET4.X 解决方法

    WIN 10系统安装Visual Studio 2012新建ASP.NET MVC 4 WEB 应用程序出错 有些图片是网上截取而来,之前光顾着处理问题而忘记截图了,提示的ASP.net 版本有些不同 ...

  8. 【2039】checker(Dp)

    我今天脑子貌似又好使了一点,可以做一做DP中的水题了. 这个题难度蓝色,纯属是做的人太少了虚高. 这个题很显然的是可以用一个顺序一个逆序这两个大水转移方程轻松转移出到达这个地方最少需要的棋子数量,然后 ...

  9. 【bzoj1260】涂色paint[CQOI2007](区间dp)

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1260 这道题其实和codeforces607B有点像,然而做过原题的我居然没看出来.. ...

  10. linux学习(rz和sz命令的安装和使用)

    lrzsz的安装 [root@spark1 ~]# yum install lrzsz rz用法 终端直接输入rz,出现文件选择对话框,选择要上传的文件就ok sz用法 下载filename文件: s ...