10信号量与管程

18.1信号量

回顾

■并发问题

多线程并发导致资源竞争

■同步概念

协调多线程对共享数据的访问

任何时刻只能有一个线程执行临界区代码

■确保同步正确的方法

底层硬件支持

高层次的编程抽象

基本同步方法

10信号量与管程_第1张图片

信号量(semaphore)

■信号量是操作系统提供的一种协调共享资源访问的方法

软件同步是平等线程间的一种同步协商机制(线程是平等的)

OS是管理者,地位高于进程

用信号量表示系统资源的数量

■由Dijkstra在20世纪60年代提出

■早期的操作系统的主要同步机制

现在很少用(但还是非常重要在计算机科学研究)

■信号量是一种抽象数据类型

·由一个整形(sem)变量(共享资源数目)和两个原子操作组成

·P()(Prolaag(荷兰语尝试减少))

sem减1

如sem<0,进入等待,否则继续

·V()(Verhoog(荷兰语增加))

sem加1

如sem≤0,唤醒一个等待进程

信号量的特性

■信号量是被保护的整数变量

初始化完成后,只能通过P()和V()操作修改

由操作系统保证,PV操作是原子操作

■P()可能阻塞,V()不会阻塞

■通常假定信号量是“公平的”

线程不会被无限期阻塞在P()操作

假定信号量等待按先进先出排队

自旋锁能否实现先进先出?

自旋锁是需要占用CPU随时随地去查标志,有可能临界区的使用者退出的时候它刚改完标志,下一个进入者哪个线程去查,那它就能进去,如果说运气不好,正好是这个资源变成有效的时候,你去查的时候在你之前就有一个人已经查过了,就没有办法按照你等待的这个顺序来执行。

信号量的实现

10信号量与管程_第2张图片

18.2信号量的使用

精髓:

基本原理:两个或多个进程可以通过简单的信号进行合作,一个进程可以被迫在某一位置停止,直到它接收到一个特定的信号。任何复杂的合作需求都可以通过适当的信号结构得到满足。为了发信号,需要使用一个称做信号量的特殊变量。信号量分类

■可分为两种信号量

·二进制信号量:资源数目为0或1(有些系统称为互斥锁)

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

·两者等价

基于一个可以实现另一个

■信号量的使用

·互斥访问

■临界区的互斥访问控制

·条件同步

线程间的事件等待

用信号量实现临界区的互斥访问

用一个信号量来对应一个临界区,,通过mutex的值来确定该资源的情况,P()减一V()加一,但mutex为负值的时候表示使用该资源的线程有在排队的,这样来实现互斥访问

10信号量与管程_第3张图片

用信号量实现条件同步

也是通过condition这个值来控制的,有一个资源B只在使用,只用通过V()操作加一后,condition的值小于等于0就知道有另一个线程A在等他,然后唤醒A。


10信号量与管程_第4张图片

生产者-消费者问题

10信号量与管程_第5张图片

用信号量解决生产者-消费者问题

10信号量与管程_第6张图片
10信号量与管程_第7张图片

P、V操作的顺序有影响吗?

P、V颠倒会出现死锁,原因是先检查空、满再去申请互斥访问,如果申请了互斥访问,申请的进程已经占用了临界资源,其他进程不能读写,但是里面发现又是满的(写者)或者是空的(读者),写也写不下去,读也读不到,其他进程也不能申请这个临界区,所以形成死锁。

使用信号量的困难

■读/开发代码比较困难

程序员需要能运用信号量机制

■容易出错(忘了一个P/V操作或者操作顺序颠倒)

使用的信号量已经被另一个线程占用

忘记释放信号量

■不能够处理死锁问题

概念:信号量的关键之处是它们原子地执行。

SMP系统必须提供其他加锁技术(如自旋锁),以确保wait()和signal()(即P()V())可原子地执行。

18.3管程

基本同步方法

10信号量与管程_第8张图片

管程(Moniter)

■管程是一种用于多线程互斥访问共享资源的程序结构

采用面向对象方法,简化了线程间的同步控制

任一时刻最多只有一个线程执行管程代码

正在管程中的线程可临时放弃管程的互斥访问,等待事件出现时恢复

■管程的使用

在对象/模块中,收集相关共享数据

定义访问共享数据的方法

概念:管程类型提供了一组由程序员定义的、在管程内互斥的操作。

管程的组成

■一个锁(入口)

控制管程代码的互斥访问

■0或者多个条件变量

管理共享数据的并发访问

10信号量与管程_第9张图片

只允许一个线程在管程内部执行,如果说在这个内部,没有其它共享数据的话这时候呢就和临界区是完全一样的

管程特有:用来管理共享数据的并发访问需要这些共享资源的时候,与相应的条件变量对应的互斥操作才能执行

条件变量(Condition Variable)

■条件变量是管程内的等待机制

进入管程的线程因资源被占用而进入等待状态

每个条件变量表示一种等待原因,对应一个等待队列

条件变量仅有的操作wait和signal

■Wait()操作

将自己阻塞在等待队列中

被signal()唤醒一个等待者或释放管程的互斥访问

■Signal()操作

将等待队列中的一个线程唤醒

如果等待队列为空,则等同空操作

条件变量实现

10信号量与管程_第10张图片

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

10信号量与管程_第11张图片

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

10信号量与管程_第12张图片

Hansen管程与Hoare管程

10信号量与管程_第13张图片

18.4哲学家就餐问题

10信号量与管程_第14张图片

方案1(信号量)

10信号量与管程_第15张图片

方案2(临界区)

10信号量与管程_第16张图片

方案3(保证每个哲学家拿起不同方向的叉)

10信号量与管程_第17张图片

18.5读者-写者问题

10信号量与管程_第18张图片

用信号量解决读者-写者问题

10信号量与管程_第19张图片
10信号量与管程_第20张图片

用管程解决读者-写者问题

10信号量与管程_第21张图片
10信号量与管程_第22张图片
10信号量与管程_第23张图片

精髓:

17、18小结

现代操作系统的核心是多道程序设计、多处理器和分布式处理器,这些方案的基础以及操作系统设计技术的基础是并发。当多个进程并发执行时,不论是在多处理器系统的情况下,还是单处理器多道程序系统中,都会产生冲突和合作的问题。

并发进程可以按多种方式进行交互。互相之间不知道对方的进程可能需要竞争使用资源,如处理器时间或对I/O设备的访问。进程间由于共享访问一个公共对象,如一块内存空间或一个文件,可能间接知道对方,这类交互中产生的重要问题是互斥和死锁。

互斥指的是,对一组并发进程,一次只有一个进程能够访问给定的资源或执行给定的功能。互斥技术可以用于解决诸如资源争用之类的冲突,还可以用于进程间的同步,使得它们可以合作。后一种情况的一个例子是生产者/消费者模型,一个进程向缓冲区中放数据,另一个或更多的进程从缓冲区中取数据。

支持互斥的第二种方法涉及使用专门的机器指令,这种方法减少了开销,但由于使用了忙等待,效率较低。

支持互斥的另一种方法是在操作系统中提供相应的功能,其中最常见的两种技术是信号量和消息机制。信号量用于在进程间发信号,并可以很容易地实施一个互斥协议。消息对实施互斥是很有用的,它还为进程间的通信提供了一种有效的方法。

你可能感兴趣的:(10信号量与管程)