操作系统-2.3同步与互斥
1. 概念
- 临界资源:一次仅允许一个进程使用的资源
- 访问过程:进入区(检查)-临界区(访问)-退出区-剩余区
- 同步:直接制约关系,源于进程间相互合作
- 互斥:间接制约关系
2.互斥实现方法
①软件实现
- 一、单标志法

两个进程轮流进入临界区
不足:若一个无法不不再进入,另一个也将无法进入(违背“空闲让进”原则)
- 二、双标志先检查法

不足:可能同时进入临界区。即检查对方标志后和设置自己标志之前可能发生进程切换(违背“忙则等待”原则)
- 三、双标志后检查法

不足:两个都想进时谁都进不了(违背“空闲让进”、“有限等待”原则)
- 四、Peterson算法(四种算法中最好)

②硬件实现
- 中断屏蔽方法(最简单,效率降低,不适用多处理系统)
- 硬件指令方法——TestAndSet指令(原子操作,适用多处理系统,但违背“让权等待”)
- 硬件指令方法——Swap指令
3.信号量
一个变量。表示系统中某种资源的数量。
- ①整型信号量
操作:初始化、wait(P操作:“申请”)、signal(V操作:“释放”)
缺陷:不满足“让权等待”
⭐②记录型信号量
在整型基础上加一个进程链表L

value初值表示系统中某种资源的数目。

- 一次P操作(wait)会执行value–,一次V操作(signal)会执行value++
- 当value–后剩余资源数**<0时,主动调用block原语进行自我阻塞**,进程被放入等待队列中
- 当value++后剩余资源数依然**<=0**,说明还有进程在等待,在V操作后主动执行wakeup原语用来唤醒等待队列 中对头的进程
该机制遵循“让权等待”
实现进程互斥、同步
①互斥
初始化互斥信号量为1
临界区之前对信号量执行P操作
临界区之后对信号量执行V操作
- P、V成对出现
②同步
初始化信号量为0
判断先后顺序(例x、y)
x之后执行V
y之前执行P
4.经典同步问题
①生产者-消费者
思考:为什么不能交换相邻P操作(empty和mutex)?
如果mutex在前,mutex变为0,若此时缓冲区无空位(empty=0,full=n),生产者被阻塞。然而消费者执行时由于mutex=0也被阻塞,无法释放缓冲区,出现死锁。
∴ 互斥的P操作一定在同步的P操作之后
但V操作可以颠倒,因为不会导致阻塞
②多生产者-多消费者问题

思考:可不可以删掉互斥信号mutex?
在本题中删掉是可以的。因为缓冲区大小=1,最多只允许一个进程访问。
但如果缓冲区大小>1则必须专门设置mutex来保证互斥访问!
③读者-写者问题
互斥:写—写、读—写(读—读可以同时)

引入count变量,只有count==0时需要在读之前加锁(既阻塞写进程,又保证后续读操作不被阻塞)
同时使用mutex来保证对count的互斥访问,防止在判断count时切换导致错误。
问题:读进程优先级更高,即如果源源不断地有读进程,写进程会“饿死”
进阶版:

增加一个变量w实现读写公平,解决写进程饥饿问题。
④哲学家进餐问题
需要避免每个人拿一支筷子陷入”死锁“
- 方案1:最多n-1个人能拿筷子
- 方案2:奇数号先拿左边,偶数号先拿右边
- 方案3:仅当左右2支筷子都能用时才允许拿筷子
5.管程
是什么
进程同步工具,保证进程互斥
组成
- ① 名称
- ② 管程内部共享数据结构说明
- ③ 对
②操作的一组过程(函数) - ④ 对
②设置初始值的语句
管程像一个类,将共享资源的操作封装起来
管程vs.信号量
同:都有类似P/V操作
异:管程条件变量没有值,仅有“排队等待”功能;信号量有值


