并发
- 并发进程的特点
- 分类
- 互斥关系:对资源共享引起,是间接制约关系。
- 同步关系:协作完成同一个任务、需要互相等待同步引起,是直接制约关系。
- 前序关系:由互斥、同步关系引起,决定各个进程的创建和终止时间。
- 顺序
- 间接制约关系的进程可以并发,但是可能会互斥执行。
- 直接制约关系的进程要顺序执行。
- 分类
- 互斥
- 临界区
- 临界资源:一次只允许一个进程访问的共享资源。
- 临界区:访问临界资源的必须互斥执行的程序。
- 进入临界区的准则
- 互斥使用:不能有两个或以上的进程在临界区执行。
- 让权等待:等待进入的进程,要释放 CPU 并阻塞等待。
- 有空让进:在临界区外的进程不可以阻止其他进程进入临界区。
- 有限等待:等待过程不可以无限长。
- 软件实现
- 实现复杂,不够灵活。
- 硬件实现
- 关中断:简单、限制了并发能力、使进程权限过高、对多 CPU 无效。
- 硬件指令:原子变量 CAS,实现自旋锁,会浪费 CPU 时间。
- 信号量
- 信号量可以完成互斥功能,并且可以使进程阻塞等待,不会浪费 CPU。
- 临界区
- 信号量
- 定义
- 信号量包含
value和一个进程队列(指针)processes。 value大于等于 时表示可以资源数量,小于 时表示等待进程数量。
- 信号量包含
- 操作
- 信号量包含 P 操作(acquire)和 V 操作(release)。
- P:表示获取资源。递减
value,如果递减后小于 ,则把当前进程加入队列。 - V:表示释放资源。递增
value,如果队列中有进程,取出一个并唤醒。 - P/V 操作是原语,不可中断。
- 实现互斥锁
- 对于一个需要互斥保护的资源,定义一个信号量
mutex,初值为 。 - 访问资源时,使用
P(mutex),不需要访问时,使用V(mutex)。 mutex.value的取值为 。
- 对于一个需要互斥保护的资源,定义一个信号量
- 实现通道/同步队列/MPMC
- 对于一个长度为 的通道,有三种资源:
- 空位置:用
empty表示,初值为 (通道初始为空)。 - 已写位置:用
full表示,初值为 。 - 通道修改权限:用
mutex表示,初值为 。
- 空位置:用
- Send/Produce:按顺序执行
P(empty)、P(mutex)、插入、V(full)、V(mutex)。 - Receive/Consume:按顺序执行
P(full)、P(mutex)、删除、V(empty)、V(mutex)。 mutex的使用:- 对于 ,可能存在多个进程可以同时修改通道,需要用互斥锁。
- 对于 ,可以不需要
mutex,empty和full之间的关系保证不会有竞争。
P(empty)/P(full)和P(mutex)不可以交换,否则可能造成死锁。
- 对于一个长度为 的通道,有三种资源:
- 实现读写锁
- 使用以下数据:
- 写权限:
wmutex信号量,初值为 。 - 修改读进程数权限:
rmutex信号量,初值为 。 - 读进程数:
count,初值为 。
- 写权限:
- 读:按顺序执行:
P(rmutex)。- 如果
count等于 ,则P(wmutex),因为接下来开始有读操作,不可以写。 - 递增
count。 V(rmutex)。- 读操作。
P(rmutex)- 递减
count。 - 如果
count等于 ,则V(wmutex),因为最后一个读操作已完成,接下来可以写。 V(rmutex)。
- 写:按顺序执行:
P(wmutex)。- 写操作。
V(wmutex)。
- 使用以下数据:
- 定义
- 高级通信
- 方式
- 消息缓冲:从发送进程复制消息体到系统缓冲区,再把缓冲区添加到接收进程 PCB(无复制)。
- 信箱
- 管道:是文件,但在硬盘上无内容。连接写进程和读进程。
- 共享内存:最快捷。
- 方式
- 死锁
- 必要条件
- 互斥条件:需要访问临界资源。
- 保持和等待条件:进程请求其他资源而阻塞时,不释放已获得资源。
- 不剥夺条件:已经分配给进程的资源只能由进程释放。
- 循环等待:每个进程等待另外一个进程的资源,最终依赖于自身。
- 解决方法
- 鸵鸟算法:忽略死锁。
- 预防死锁:破坏死锁的必要条件,使死锁不可能发生。
- 避免互斥条件:用 spooling 技术把单个设备改造为多个设备,但不适用于所有设备,也可能失败。
- 避免保持和等待条件:提取获取所有需要的资源,但难以预测需要的资源有哪些。
- 避免不剥夺条件:允许资源被其他进程释放,但代价高、破坏正确性。
- 避免循环等待:为资源编号,所有进程按顺序获取,但难以找到符合条件的编号。
- 避免死锁:分配资源过程中检查分配,防止系统进入不安全状态。
- 银行家算法。
- 检测死锁并恢复。
- 银行家算法
- 设有 个进程和 种资源,每种资源可以有不同的数量。
- 符号定义:
- 已分配资源矩阵:每一行对应进程,每一列对应资源,矩阵元素表示进程已获得的这种资源数量。
- 剩余请求资源矩阵 :每一行对应进程,每一列对应资源,矩阵元素表示进程未来还需要的这种资源数量。
- 剩余资源向量 : 行向量,每一列对应资源的剩余数量。
- 判断状态是否安全:
- 若 存在一行 ,使得 ,则当前状态不会死锁,否则当前状态不安全。
- 若找到 ,则假设进程 接下来可以获得资源并运行结束,标记为终止,收回 并加到 上。
- 重复,直到所有进程都标记为终止,则此状态安全,否则不安全。
- 死锁检测和恢复
- 检测方法:
- 把进程和资源都抽象为有向图节点。
- 如果进程 已获得资源 ,则连边 ;如果 请求 ,则连边 。
- 检查有向图是否存在回路,如果存在则有死锁。
- 恢复方法:
- 终止进程:
- 终止所有进程
- 一次终止一个死锁进程,直到死锁接触。
- 资源剥夺:
- 直接取走资源给另外一个进程使用。
- 回滚进程到获取资源前的检查点。
- 终止进程:
- 检测方法:
- 必要条件