2.3 同步与互斥
引入同步的原因是
【进程的并发具有异步性,以各自独立不可预知的速度推进】
2.3.1 同步与互斥的基本概念
1.临界资源:一次仅仅允许一个进程所使用的资源叫做临界资源
。
2.同步:进程同步是确保多个进程在共享资源的访问过程中按照一定规则进行协调和管理的过程。
基本原则:
- 空闲让进
- 忙则等待
- 有限等待
- 让权等待
(得不到处理机就进入阻塞态)
3.互斥:间接制约关系。一次只允许一个进程使用资源。
2.3.2 实现临界区互斥的进本方法
1.软件实现方法:
(1)算法一:单标志法:【只检查不上锁】
只有一个变量turn用于标记允许哪个进程访问。
资源只能轮流使用。若当前标记的是对方,即使对方没有使用,自己也不能使用
违背"空闲让进"原则:若当前标志不是当前需要访问的进程的标志,将会一直忙等。
(2)算法二:双标志法先检查:【先检查后上锁】(满足了“空闲让进”原则,允许交替使用)
使用bool型数组记录,哪个进程正在访问哪个进程的记录就位true
先检查对方是否占用资源,然后自己锁定资源
违背"忙则等待"原则:若两个进程的检查和上锁是交替运行的,会导致两个进程同时占用资源。(下图为例)【按照1,2,3,4顺序执行】
(3)算法三:双标志法后检查:【先上锁后检查】
使用bool型数组记录,哪个进程正在访问哪个进程的记录就位true
先对资源上锁,然后检查对方是否在使用
违背"空闲让进"原则:若两个进程的上锁和检查时交替运行的,会导致两个进程同时被对方锁住。会造成死锁(饥饿)
(下图为例)【按照1,2,3,4顺序执行】
(4)算法四:皮特森算法:【结合算法一和算法三的思想】
同时使用bool数组和turn变量
bool数组表示进程想使用资源的意愿,turn表示可以让给其他进程先使用
先表明自己想使用资源,然后表示可以让其他进程先使用。若turn不是其他进程或其他进程没有使用资源的意愿,自己就可以占用资源。
违背"让权等待"原则:若资源不能得到,也不能下处理机。不存在死锁(饥饿)
单标志法 | 双标志法先检查 | 双标识法后检查 | 皮特森算法 | |
---|---|---|---|---|
使用过程 | 轮流使用 | 先检查其他是否正在使用,在自己上锁 | 先上锁,再检查其他进程是否在使用 | 先表明自己想使用,再把使用权让给其他进程,若其他进程没有使用的意愿或使用权不在其他进程,则自己可以使用 |
缺陷 | 违背"空闲让进" | 违背"忙则等待" | 违背"空闲让进" | 违背"让权等待" |
使用变量 | 一个公用整形变量"turn" | 一个bool数组"flag" | 一个bool数组"flag" | 一个公共整形变量"turn"和一个bool数组"flag" |
2.硬件实现方法:
(1)中断屏蔽字
使用关中断和开中断来
禁止切换进程
,就不会出现互斥的问题。
优点:简单高效
缺点:不适合多处理机,只适合内核
进程使用。可能会导致系统效率降低。
(2)硬件指令方法
由硬件逻辑上实现,不会被中断。
不能实现让权等待,产生饥饿现象
- TestAndSet指令【一边检查一边上锁】
本身为原子操作,不会被中断,也不允许
关中断
注意!!!【若长期使用,且在等待期间处于关中断状态,其他进程的操作会收到影响,从而影响到整个系统】
优点:实现简单。适合多处理机系统【与总线相关】。
缺点:不满足"让权等待"
,会持续等待
- swap指令【一边检查一边上锁】
本身为原子操作,不会被中断,也不允许
关中断
优点:实现简单。适合多处理机系统【与总线相关】。
缺点:不满足"让权等待"
,会持续等待
硬件实现的优点:允许任意数量进程,单处理机和多处理机都适用!!!
硬件实现的缺点:不能让权等待,会产生`饥饿现象`
2.2.3 互斥锁
通过原子操作
函数acquire()
获得锁和release()
释放锁。
属于`自旋锁`,需要循环忙等。{TSL,SWAP,单标志}都属于`自旋锁`
只适用于多处理机系统,互斥会导致进程处于持续等待的状态。
`为什么说适用于多处理机`:在忙等期间,单处理机会切换进程。若使用时间短但是使用频率很高造成切换进程的开销会增大。
多处理机只会使用`一个核`的资源,不影响其他核心。`单处理机`吃掉了唯一的核。
2.2.4 信号量{考试题目默认是记录型变量}
信号量用于解决
同步和互斥
问题。
使用原语
【wait(s)/p操作】申请资源
和【signal(s)/v操作】释放资源
p,v方式是一种低级的通信方式【相对于"共享存储",“消息传递”,“管道通信”】
1.整形信号量【不满足让权等待】
只有一个整数变量
S
用于记录资源的数量
`S>0说明有空闲资源`
`S<=0说明无空闲资源,其绝对值就是进程的等待数量`\\注意不是阻塞,而是等待。阻塞会放弃处理机,等待不会放弃处理机。
过程描述:
(1)wait函数用于申请资源,若s<=0
,说明无资源可以使用,将进入循环等待阶段。
(2)signal函数用于释放资源(s=s+1)
。若wait在等待时发现s>0
,循环等待可以结束。
2.记录型信号量【满足让权等待】
使用结构类型变量semaphore记录资源数S和阻塞进程队列L
`s>0说明有空闲资源,s<0说明无空闲资源,s的绝对值就是阻塞队列中进程的个数`
`L代表申请资源却得不到资源的进程的队列`
过程描述:
(1)wait函数用于申请资源,先资源数-1
,若s<=0
,说明无资源可以使用,将插入阻塞队列队尾
,且自动放弃处理机。
(2)signal函数用于释放资源(s=s+1)
。先资源数+1
然后从阻塞队列唤醒队首
进程,使其从阻塞态
变成就绪态
,等待处理机调度。
3.利用信号量实现同步,互斥和前驱关系
互斥设置信号量,整形s初始化设置为1,结构型s设置为资源数量。为0就阻止其他进程进入
(先p后v)
同步设置信号量初始值由用户确定【可能已经存在资源】
(先v后p)
2.3.5 管程【软件
】
每次仅仅允许一个进程在管程内执行某个内部过程/函数。
外部进程/线程只能通过管程提供的特定"入口"访问。每次只开放一个入口。
管程组成
{
1.
管程名称
2.
局部于管道内部的共享数据结构说明
3.
对于该数据结构操作的函数
4.
初始化内部数据语句
管程组成\begin{cases}1.管程名称\\ 2.局部于管道内部的共享数据结构说明\\ 3.对于该数据结构操作的函数\\ 4. 初始化内部数据语句 \end{cases}
管程组成⎩
⎨
⎧1.管程名称2.局部于管道内部的共享数据结构说明3.对于该数据结构操作的函数4.初始化内部数据语句
对比结构型信号量
和管程
。
结构型信号量 | 管程 | |
---|---|---|
阻塞时机 | 在wait操作/p操作内检查到资源不足 | 1.在使用过程 前已有进程使用,会被阻塞在过程 外。2.过程内部检测到没有资源 |
signal/v操作 | 包含了资源+1和唤醒操作 | 其他过程给资源+1,调用signal时才唤醒 |
管程
信号量
相似点:条件变量的wait/signal操作类似信号量的P/V操作,可实现进程的阻塞
和唤醒
不同点:条件变量没有值
,仅实现排队功能
。信号量是有值的,反映剩余资源数量
。管程
用共享数据结构记录。