双标志先检查法(Two-Flag Algorithm)
定义:
双标志先检查法(Two-Flag Algorithm)是一种解决进程互斥的算法,它是基于两个共享变量(标志)来保证两个进程之间的互斥访问。与单标志法相比,双标志法通过使用两个标志变量来避免单一标志法中的忙等待问题,并进一步提高互斥的效率和公平性。
原理:
双标志法的核心思想是使用两个共享标志(通常是 flag0 和 flag1),每个进程都有一个标志位,用来指示该进程是否准备进入临界区。当一个进程希望进入临界区时,它首先将自己的标志设置为 true,然后检查另一个进程的标志。如果另一个进程也希望进入临界区,它必须等待。双标志法通过双重检查机制,确保只有一个进程能够进入临界区。
双标记先检查法 (Double Flag, Check First):
A 标志 flag[0] ,B 标志 flag[1]
- **核心思想:**先看对方想不想进,我再决定自己想不想进
- 逻辑流程(以进程A为例) :
- while(flag1==1); // 先检查对方是否在临界区或想进入临界区
- flag0=true;// 确认对方不在,自己再举手
- 访问临界区...
- flag0=false;// 访问完毕,放下手
- 缺点: 违背"忙则等待"原则。
- 如果A检查完 flag1为false 后,发生进程切换;
- B也检查完 flag0为false,接着切换回来。
- A设置 flag0=true 进入,B设置flag1=true进入。
- 两者会同时进入临界区,互斥失败。
双标志先检查法(Two-Flag Algorithm)
- **核心思想:**我先举手表示想进,然后再看对方想不想进。如果对方也想进,我就等一下
- 逻辑流程(以进程A为例):
- flag0=true;// 先举手,表示我想进
- while(flag1 == true);// 再检查对方是否也举手了
- 访问临界区...
- flag0=false;// 访问完毕,放下手
- **缺点:**违背"空闲让进" 和 "有限等待" 原则,可能导致死锁(饥饿)。如果A和B几乎同时执行了第1步(都举手了),然后互相在第2步检查对方,发现对方都举手了,于是双方都在死循环里等待对方先放下手,导致谁也无法进入临界区。
双标志先检查法的操作步骤:
假设有两个进程 A 和 B,它们共享两个标志位 flag[A] 和 flag[B],初始值均为 false。
进程 A 请求进入临界区:
-
先检查 :进程 A 首先检查进程 B 的标志
flag[B]。 -
判断:
-
如果
flag[B]为false(表示 B 不想进入临界区),则 A 继续下一步。 -
如果
flag[B]为true(表示 B 正在或想要进入临界区),则 A 必须一直循环等待 (忙等),直到flag[B]变为false。
-
-
后修改 :当确认
flag[B]为false后,A 将自己的标志flag[A]设置为true,表示自己现在要进入临界区。 -
进入:A 进入临界区执行代码。
进程 B 请求进入临界区:
-
先检查 :同样地,进程 B 首先检查进程 A 的标志
flag[A]。 -
判断:
-
如果
flag[A]为false,则 B 继续下一步。 -
如果
flag[A]为true,则 B 必须一直循环等待 ,直到flag[A]变为false。
-
-
后修改 :当确认
flag[A]为false后,B 将自己的标志flag[B]设置为true。 -
进入:B 进入临界区执行代码。
3. 离开临界区(释放):
-
进程完成临界区任务后,将自己的标志位设置为
false(例如 A 将flag[A]设为false)。 -
这表示它已释放临界区,允许另一个进程(B)检查到
false后进入。
双标记先检查法伪代码示例:
// 进程 A 的代码
while (true) {
// 1. 先检查对方是否想进
while (flag[B] == true);
// 2. 确认对方不想进后,再修改自己的标志
flag[A] = true;
// 3. 访问临界区
critical_section();
// 4. 退出区:释放锁
flag[A] = false;
// 5. 剩余区
remainder_section();
}
(同理,进程 B 的代码只需将上述代码中的 A 和 B 互换即可)
双标记法的工作原理:
-
设置两个标志变量
flag[A]和flag[B],初始值均为false。用于表示两个进程是否想要进入临界区。 -
进程在进入临界区之前,必须先检查 另一个进程的标志状态。只有当另一个进程的标志为
false(不想进入)时,当前进程才能继续。 -
确认对方不想进入后,当前进程将自己的标志设置为
true,然后进入临界区。 -
进程离开临界区时,将自己的标志设置为
false,允许另一个进程进入。
双标记法的优势:
避免忙等待:
- 与单标志法相比,双标志法能有效减少忙等待。通过检查两个标志,进程能够在必要时进行等待,从而提高效率。
避免竞态条件:
- 双标志法避免了竞态条件,即多个进程同时访问共享资源时产生的冲突,因为它保证在任何时刻只有一个进程可以进入临界区。
公平性:
- 双标志法通过两次检查确保了公平性。两个进程都在检查对方的标志,并以此决定是否进入临界区,从而避免了进程饥饿(starvation)问题。
双标记法的缺点:
忙等待问题:
- 双标志法仍然存在忙等待的问题。当一个进程等待时,它会不断检查标志变量的状态,浪费 CPU 时间,尤其是在进程数量多、临界区访问时间较长时,这种方式可能导致系统效率低下。
不能扩展到多个进程:
- 双标志法设计时是为两个进程而设计的。如果需要多个进程共享资源,双标志法无法直接扩展,必须使用更复杂的同步机制(如信号量、互斥锁等)。
缺乏内存和时间的优化:
- 双标志法需要两个共享标志变量,这在某些场景下可能不是最优的解决方案,尤其是当系统资源有限时。
双标记先检查法的改进:
增加时间限制或让进程睡眠:
- 为了避免忙等待带来的性能问题,可以在双标志法中引入时间限制或让进程在等待时进入睡眠状态,减少不必要的 CPU 占用。
采用信号量或互斥锁:
- 在多进程或多线程环境中,使用信号量(semaphore)或互斥锁(mutex)来代替双标志法,能够更高效地管理资源的访问,并且避免忙等待、进程饥饿等问题。
总结
双标志先检查法试图通过两个标志位来控制两个进程的互斥。它虽然改善了单标志法必须轮流执行的限制,但由于检查和修改标志位的操作无法保证原子性,它违背了"忙则等待"原则,存在严重的竞态条件,无法真正实现进程互斥。此外,它依然存在忙等待的缺陷,且仅适用于进程较少的简单场景。在现代复杂的操作系统中,通常会选择更高级的同步机制(如信号量、互斥锁等)来实现进程同步。