四、并发:互斥与同步(一)
主要内容
- 并发原理
- 互斥的软硬件实现
- 信号量
- 管程
- 消息传递
- 读者-写者问题
操作系统设计的核心问题
- 进程与线程的管理
- 多道程序设计技术————管理单【核】处理器系统中的多个进程
- 多处理技术————管理多【核】处理器系统中的多个进程
- 分布式处理技术————管理多台分布式计算机系统中的多个进程
- 并发 多道程序/多任务处理
- 所有问题的基础/根源
- 操作系统设计的基础
- 并发发生的场合
- 多个应用程序(多道)
- 结构化应用程序(模块)
- 操作系统结构(结构化/模块)
- 并发相关术语
- 临界区:不允许多个进程同时进入的一段访问共享资源的代码
- 死锁:两个及以上的程序,因每个进程都在等待其他进程操作(如释放资源)而不能继续执行
- 互斥:一个进程在临界区访问共享资源时,不允许其他进程进入访问
- 竞态:多个进程/线程读写共享数据,其结果依赖于其执行的相对速度/相对时序
- 饥饿:可运行进程长期未被调度执行
并发性
- 并发性引发的问题
- 资源竞争、共享、分配管理困难
- 难调试(执行结果不可复现)
- 进程的相互作用
- 通过共享的竞争
- 通过共享的合作
- 通过通信的合作
- 进程的互斥机制
- 软件方法(Dekker算法、Peterson算法)
- 硬件方法(关中断、专用指令TestSet、Exchange)
4.1并发的原理

- 并发的基本特征
- 并发
- 在同一时间段内活动的进程或线程,在此期间,它们可能交替地共享相同的资源
- 异步性
- 相对执行速度不可预测
- 多道程序系统的基本特性
- 影响进程执行速度的因素
- 其他进程活动
- 操作系统处理中断的方式
- 操作系统的调度策略
- 问题
- 全局资源的共享充满危险
- 操作系统对资源分配的管理难以达到最优
- 调试程序设计错误非常困难(不可再现性)
- 并发
4.1.1并发产生的错误

4.1.2竞态
- 在并发环境中发生
- 多个进程共享数据
- 多个进程读取且至少一个进程写入
- 共享数据产生错误结果,具体结果取决于进程执行的相对速度
4.1.3操作系统必须考虑的问题
- 并发环境中跟踪每个进程,知道它们的状态
- 为每个进程分配和回收各种资源
- 处理机
- 存储器
- 文件
- I/O设备
- 保护进程拥有的数据和物理资源
- 防止并发竞态发生,保证进程的结果正确,与相对执行速度无关
- 内核并发发生竞态
- 用户进程并发竞态
- 防止并发竞态发生,保证进程的结果正确,与相对执行速度无关
4.1.4进程间的相互作用
- 间接作用
- 因为共享而竞争
- 通过共享实现合作
- 直接作用
- 通过通信的合作
进程间的竞争现象
- 特点
- 独立设计的进程,每个进程不知道其他进程的存在
- 两个或更多进程在各自的执行过程中需要访问相同的资源(I/O设备、存储器、CPU、时钟等)
- 进程之间没有信息交换的要求
- 相互间产生的影响
- 执行结果不会受影响
- 执行时间受到影响
- 竞争引发的控制问题
- 互斥
- 死锁
- 饥饿
- 互斥的相关概念
- 互斥
- 多个进程需要访问一个共享的资源时,任何时候只能有一个访问这个资源
- 临界资源
- 不可操作使用的资源
- 临界区
- 访问临界资源的那部分代码
- 死锁
- 一组进程中,每个进程都无限等待该组进程中另一进程所占用的资源
- 饥饿
- 一组进程中,某个或某些进程无限等待该组进程中其他进程所占用的资源
- 互斥
- 进程间通过共享合作
- 特点
- 没有意识到其他进程的存在,需要维护数据的完整性
- 共享变量、文件或数据库等
- 相互间产生的影响
- 执行结果可能会受影响
- 执行时间受影响
![image]()
- 共享引发的控制问题
- 互斥、死锁、饥饿、数据一致性
- 特点
4.1.5解决互斥问题的要求
- 进程并发,完全自由无约束
- 互斥是并发中防止产生错误的一种模式
- 操作系统解决互斥的机制/方案,要满足一定的条件
- 具有相同资源或共享对象的临界区的所有进程中,一次只允许一个进程进入临界区
4.1.6解决互斥问题的条件
- 具有相同资源或共享对象的临界区的所有进程中,一次只允许一个进程进入临界区(强制排它)
- 在非临界区停止的进程不干涉其他进程(充分并发)
- 没有进程在临界区中时,任何需要访问临界区的进程必须能够立即进入(空闲让进)
- 不允许出现一个需要访问临界区的进程被无限延迟(有限等待)
- 相关进程的执行速度和处理机数目没有任何要求或限制(满足异步)
- 当进程不能进入临界区,应该立即释放处理机,防止进程忙等待(让权等待)
4.1.7互斥机制应用框架

- N个进程并发,竞争资源Ra
- 每个进程都会有一段代码操作Ra
- 为了确保结果正确,必须互斥操作Ra
4.2实现互斥的方法
- 软件方法:
- Dekker算法
- Peterson算法
- 硬件方法
- TestSet指令
- Exchange指令
- 操作系统或程序设计语言的支持
- 信号量
- 管程
- 消息机制
第一种尝试:用turn标记位轮转

- 可以保证互斥
- 硬性规定进入的顺序
- 两个进程轮流进入临界区
- 存在问题
- 忙等待:为了等待一事件发生,重复执行一段循环代码----白白消耗CPU时间
- 必须轮流进入临界区----不合理,限制推进速度
- 如果一个进程失败,另一个进程将被永久阻塞
- 分析:难以满足并发需求
第二种尝试:用flag[i]标志进程i进入临界区

- 每个进程应有自己进入临界区的“钥匙”
- 进程设置标志表示自己进入和离开
- 可以检查对方标志
- 先查对方标志再设置自己进入临界区的标志
- 存在问题
- 一个进程在临界区内失败,另一进程永远被阻塞
- 不能保证互斥
- 分析:错误方案,不能保证进程的运行结果与执行速度无关
- 失效示意图
![image]()
第三种尝试:将flag[i]标志的设置,提前到循环等待之前

- 第三种尝试的特点:先表示自己想进入临界区,再检查对方是否已进入
- 可以保证互斥
- 问题:可能导致死锁
- 死锁产生的原因:两个进程都要坚持进入
![image]()
第四种尝试:在循环等待中用延时给其他进程进入的机会

- 解决思路:礼让,等一会
- 可以保证互斥
- 问题:会导致活锁
- 死锁与活锁
- 死锁:都想进入临界区,但都不能进入
- 活锁:本来可以进入临界区,但均不能进入
- 活锁时序图
![image]()





浙公网安备 33010602011771号