在IPC问题中,避免竞争条件实现互斥有多种方案:
- 1.屏蔽中断
- 2.锁变量
- 3.严格轮换法
- 4.Peterson解法
- 5.TSL指令
避免竞争条件 :
1 -任何两个进程不能同时处于其临界区
2 -不应对CPU的速度与数量进行比较
3 -临界区外运行的进程不得阻塞其他进程
4 -不得使进程无限期等待进入临界区
本文中着重介绍严格轮换法:
所谓的严格轮换法就是引入一个变量turn指示当前轮到哪个进程进入临界区,比如目前有两个进程0和1,一开始,我们让turn为0,进程0检查turn是否为0,当前turn为0,所以进程0进入临界区,而进程1发现turn为0,所以在外等待,一直等待turn的值变为1,像这样连续测试一个变量直到某个值出现为止的过程称为忙等待,在进程0退出临界区后,将turn置为1,这时进程1进入临界区,进程0完成剩余的工作,如此循环。
下面利用代码来直观理解一下流程:
代码借鉴于:https://blog.csdn.net/qq_41636947/article/details/101105143
#include <windows.h>
#include <cstdio>
#include <iostream>
#include <process.h>
using namespace std;
int turn; //全局变量
CRITICAL_SECTION cs; //临界区
// DWORD == double word 一般用来保存地址或者存放指针
// WINAPI == _stdcall
// LPVOID == void* 没有类型的指针
DWORD WINAPI fun_1(LPVOID p){
while(TRUE){
while(turn!=0);
EnterCriticalSection(&cs); //进入临界区
cout<<"process 0: ";
turn = 1;
cout<<turn<<'\n';
LeaveCriticalSection(&cs); //离开临界区
}
}
DWORD WINAPI fun_2(LPVOID p){
while(TRUE){
while(turn!=1);
EnterCriticalSection(&cs);
cout<<"process 1: ";
turn = 0;
cout<<turn<<'\n';
LeaveCriticalSection(&cs);
}
}
int main()
{
InitializeCriticalSection(&cs);
HANDLE th1,th2; //创建两个进程
th1 = CreateThread(nullptr,0,fun_1, nullptr,0, nullptr);
th2 = CreateThread(nullptr,0,fun_2, nullptr,0, nullptr);
Sleep(1000); //让进程0和进程1有足够的反应时间
CloseHandle(th1);
CloseHandle(th2);
return 0;
}
代码运行结果:
result
存在的问题
从结果来看,进程0和进程1的确在进入临界区时互斥,但这个方法还是存在一个竞争条件。
思考一下,当进程1退出临界区并将turn设置为0时,进程1进入非临界区工作,这时进程0检查到turn为0,所以进程0进入临界区,而且进程0很快离开临界区(这次非常快完成工作),然后将turn置为1,同样很快离开非临界区进入下一轮循环,但此时,进程1还在非临界区工作,而进程0就会被阻塞,而这种情况不满足避免竞争条件中的3:临界区外运行的进程不能阻塞其他进程,所以严格轮换法不是一种很好的解决方案。
网友评论