信号量与管程

一、概述

 信号量是操作系统提供的一种协调共享资源访问的方法。和用软件实现的同步比较,软件同步是平等线程间的的一种同步协商机制,不能保证原子性。而信号量则由操作系统进行管理,地位高于进程,操作系统保证信号量的原子性。

信号量是跟锁机制在同一个层次上的编程方法。

管程是为了解决信号量在临界区的PV操作上的配对的麻烦,把配对的PV操作集中在一起,生成的一种并发编程方法。其中使用了条件变量这种同步机制。

二、信号量

1)概述

  信号中包括一个整形变量,和两个原子操作P和V,其原子性由操作系统保证,这个整形变量只能通过P操作和V操作改变。

P意味着信号量值减1,减完之后如果信号量值小于0,则说明资源不够用的,把进程加入等待队列。

  V意味着信号量值加1,加完之后如果信号量值小于等于0,则说明等待队列里有进程,那么唤醒一个等待进程。

  信号量的等待进程被放在等待队列中,按先进先出的次序执行。

自旋锁不能保证进程按先进先出的次序执行,因为自旋锁的所有等待进程都在循环中忙等待,在临界区释放的那一刻,先检查到临界区为空的进程先进入临界区,没有先来后到之分。

2)具体实现:

3)信号量分类:

i)二进制信号量:资源数目为0或1

ii)资源信号量:资源数目为任何非负值

两者其实是等价的,基于一个可以实现另一个。

4) 信号量作用:

i)实现临界区的互斥访问

进入临界区之前使用P操作,如果信号量为1,则进入,且信号量设置为0。如果信号量为0,则进入等待队列。

退出临界区之后使用V操作,信号量值加1,如果信号量还小于等于0,则唤醒等待队列中的一个进程。

ii)实现条件同步

一个线程A使用P操作,一个线程B使用V操作,初始的信号量设置为0。则为了满足某个条件,必须在线程B执行之后,才可以执行线程A。用信号量可以轻松实现这一点。

 

5)用信号量实现生产者-消费者问题

  

6)使用信号量的缺陷

读/开发代码比较困难,而且PV在不同的线程里配对,容易写错。而且必须先检查资源信号量的值,再进入临界区(即先写emptyBuffers->P(),再写mutex->P()),否则所有线程都不能进入临界区。

三、管程

1)概述

管程是为了解决信号量在临界区的PV操作上的配对的麻烦,把配对的PV操作集中在一起,生成的一种并发编程方法。其中使用了条件变量这种同步机制。

管程与临界区不同的是,在管程中的线程可以临时放弃管程的互斥访问,让其他线程进入到管程中来。而临界区中的线程只能在线程退出临界区时,才可以放弃对临界区的访问。

2)管程的组成

当条件变量的数目为0时,管程和临界区相同。

3)条件变量

  一个条件变量就对应于一个等待队列,每个条件变量有一个Wait()操作和Signal()操作。

4)用管程实现生产者-消费者问题

 先进入管程,再进行判断。就是因为管程中的线程可以放弃对管程的互斥访问,交由其他线程访问管程。

(视频里说 管程可以把PV操作都集中到一个模块里,我对此有疑问。。在我看来,不就是把两个信号量表示成两个条件变量了嘛。。PV还是分散的啊。求指教)

5)管程条件变量的释放处理方式

进程A执行,被阻塞,进入等待队列,切换到进程B,当进程B执行signal操作使进程A可以执行时,有两种方式:一种是等进程B执行完再执行进程A,另一种是立即切换到进程A,等执行完进程A再切换到进程B,执行进程B。

第二种比第一种多了一次切换,所以第一种比较高效,但第二种容易证明其正确性。第一种主要用于真实OS和Java中,第二种主要见于教材中。

四、哲学家就餐问题

  

方案1:都先拿左边的叉子,再拿右边的叉子,拿不到就等着。当5个哲学家同时拿起左边的叉子时,就会引起死锁。

方案2:某一时间内,只能有一个哲学家在进餐,其他的人都不许拿叉子。结果正确,但是效率低。

方案3:按某一规律(下图是按奇偶数分类)让不同的哲学家先拿不同方向的叉子,即不是都先拿左手的叉子或右手的叉子,而是有的先拿左手的叉子,有的先拿右手的叉子。从而避免方案1中死锁的发生。

五、读者写者问题

时间: 2025-01-14 01:05:03

信号量与管程的相关文章

信号量和管程

原文地址:https://www.cnblogs.com/feng-ying/p/10659418.html

经典线程同步 信号量Semaphore

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便.下面是这几个函数的原型和使

秒杀多线程第八篇 经典线程同步 信号量Semaphore

版权声明:本文为博主原创文章,未经博主允许不得转载. 阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore

用信号量和读写锁解决读者写者问题

读者写者问题是非常经典的同步问题,本文首先用信号量来解决这个问题,并结合代码分析什么是读者优先.什么是写者优先,然后给出读写锁的解决方案,并指出在Linux下读写锁的注意事项. 读者写者问题 读者写者问题描述的是这么一种情况:对象在多个线程(或者进程)之间共享,其中一些线程只会读数据,另外一些线程只会写数据.为了保证写入和读取的正确性,我们需要保证,只要有线程在写,那么其他线程不能读,否则可能读到写了一半的数据:另外,也不能有两个线程同时写,否则导致数据错乱.当然,多个线程是可以同时读数据. 读

操作系统概念学习笔记 12 进程同步(二)管程

操作系统概念学习笔记 12 进程同步(二) 管程 基本的.高级的同步构造,即管程(monitor)类型. 使用: 管程类型提供了一组由程序员定义的.在管程内互斥的操作.管程类型的表示包括一组变量的声明(这些变量的值定义了一个类型实例的状态)和对这些变量操作的子程序和函数的实现.管程的类型表示不能直接为各个进程所使用.因此,在管程内定义的子程序只能访问位于管程内那些局部声明的变量和形式参数.类似的,管程的局部变量能被局部子程序访问. 管程结构确保一次只有一个进程能在管程内活动.不需要显示的编写同步

使用信号量控制Linux线程同步

线程同步 在现实生活中,有些东西就必须是按顺序执行的,只有我完成了以后,你才能在我的劳动成果上接着干:不能我还没有完成,你就开始干活了.这就是线程同步最直白的解释了. 在进行程序设计时,亦是如此.线程同步,同步的是什么?它同步的是对共享资源(内存区域,公共变量等)或者临界区域的访问.有的时候,这些共享 资源和临界区域,就只能容忍一个线程对它进行操作(读或者写,读操作一般不控制,主要是写操作),这个时候,我们必须要对这些共享资源或者临界区域进行同 步,那么如何对它们进行线程同步呢? 在Linux中

转---秒杀多线程第八篇 经典线程同步 信号量Semaphore

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便.下面是这几个函数的原型和使

java中的管程

前言 ? 并发编程这个技术领域已经发展了半个世纪了,相关的理论和技术纷繁复杂.那有没有一种核心技术可以很方便地解决我们的并发问题呢?这个问题如果让我选择,我一定会选择管程技术.Java 语言在 1.5 之前,提供的唯一的并发原语就是管程,而且 1.5 之后提供的 SDK 并发包,也是以管程技术为基础的.除此之外,C/C++.C# 等高级语言也都支持管程.可以这么说,管程就是一把解决并发问题的万能钥匙. 什么是管程 ? 不知道你是否曾思考过这个问题:为什么 Java 在 1.5 之前仅仅提供了 s

CS考研_统考大纲

序号 政治 外语 业务课一 业务课二 1 (101)思想政治理论 (201)英语一 (301)数学一 (408)计算机学科专业基础综合 以上是计算机全国统考考试科目,三门公共课非统考基本也都是这三个,大家如果看到非统考的科目如果是三个1,就可以直接来参考我这里列出的大纲了!所以在此,我就直接列出最近的2015年考研这四个的考试大纲: 政治101: Ⅰ.考试性质 思想政治理论考试是为高等院校和科研院所招收硕士研究生而设置的具有选拔性质的全国招生考试科目,其目的是科学.公平.有效地测试考生掌握大学本