实现临界区互斥的基本方法
一、软件实现方法
通过设置标志变量(如turn
、flag
)协调进程进入临界区,核心是在进入区检查/设置标志,在退出区重置标志。
算法 | 核心思想 | 优点 | 缺点 | 违背准则 |
1. 单标志法 | 设置 | 实现简单,严格互斥。 | 需交替进入,若 | 空闲让进(临界区空闲时不允许合法进程进入)。 |
2. 双标志先检查法 | 设置 | 可连续进入,无需交替。 | 检查和设置非原子操作:两进程可能同时通过检查,进入临界区。 | 忙则等待(多个进程同时进入临界区)。 |
3. 双标志后检查法 | 先置自己 | 避免同时进入(先占坑再检查)。 | 可能双方都置 | 空闲让进+有限等待(临界区空闲但进程无法进入)。 |
4. Peterson算法 | 结合 | 严格互斥,无饥饿,支持连续进入。 | 未实现“让权等待”(等待时CPU忙等)。 | 让权等待(可选准则,非必须)。 |
二、硬件实现方法
利用原子指令(不可中断的硬件操作)实现“检查+设置”的原子性,避免软件方法的逻辑漏洞。
1. 关中断
- 机制:进程进入临界区前关中断(禁止CPU响应中断,避免进程切换),退出时开中断。
- 优点:简单,绝对互斥。
- 缺点:
- 关中断期间CPU无法切换,系统吞吐量下降(效率低)。
- 仅适用于单CPU系统(多CPU无法通过关中断实现互斥)。
2. TestAndSet指令(TS指令)
- 原子操作:读取
lock
值并置为true
(一步完成,不可中断)。
bool TestAndSet(bool *lock) {
bool old = *lock;// 读取原值
*lock = true;// 设置为占用
return old;// 返回原值
}
互斥逻辑:
lock
初值false
(空闲)。进程进入前调用TS(&lock)
:- 若返回
false
(之前空闲),则进入临界区; - 若返回
true
(已占用),则循环等待(忙等)。 - 优点:适用于多CPU系统,实现简单。
- 缺点:忙等(未实现“让权等待”),可能饥饿。
3. Swap指令
- 原子操作:交换两个变量的值(如共享
lock
和局部key
)。
void Swap(bool *a, bool *b) {
bool temp = *a;
*a = *b;
*b = temp;
}
- 互斥逻辑:
lock
初值false
,进程P_i
设局部key=true
,循环执行Swap(&lock, &key)
:- 若
key
变为false
(交换前lock
为false
),则进入临界区; - 若
key
仍为true
(交换前lock
为true
),则继续循环。 - 特点:与TS指令逻辑等价,优缺点相同(忙等,无让权等待)。
三、软件/硬件方法的共同缺陷
- 未实现“让权等待”:等待进程循环检查标志(忙等),浪费CPU资源。
- 可能饥饿:硬件方法中等待进程随机竞争,低优先级进程可能长期等待。
核心考点 📌
- Peterson算法的优势:唯一遵循“空闲让进、忙则等待、有限等待”三大准则的软件方法,是软件互斥的最优解(但仍忙等)。
- 原子操作的重要性:硬件方法通过原子指令(TS/Swap)将“检查+设置”合并为不可中断的操作,解决软件方法的逻辑漏洞。
- 让权等待的实现:软件/硬件方法均未实现(需后续信号量机制通过阻塞/唤醒实现)。
总结:✨
软件方法通过标志变量(单/双标志法、Peterson算法)协调进程进入临界区,其中Peterson算法满足互斥、空闲让进和有限等待三大准则,但仍存在忙等问题。硬件方法(关中断、TS/Swap指令)利用原子操作确保互斥,适用于多CPU系统,但同样无法避免忙等和潜在饥饿。两类方法均未实现"让权等待",为后续信号量机制奠定基础。关键区别在于硬件方法通过原子指令解决了软件方案的逻辑漏洞,但都需结合更高级同步机制来优化资源利用率。
一句话总结:软件方法(如Peterson)通过标志协调互斥但存在忙等,硬件方法(TS/Swap)利用原子指令保证互斥但仍忙等,二者为信号量等高级同步机制奠定基础! ✨