一、进程同步机制
原则
- 空闲让进
- 忙则等待
- 有限等待
- 让权等待(可选)当进程不能进入临界区时,应立即释放CPU
二、Dekker算法
- 版本一
int turn = 0; //共享一个全局变量,初始化为0或1
turn == i; //轮到进程i进入临界区
//进程P0
do{
while(turn != 0); //判断是否轮到P0进入区;不是则等待,一直循环判断 do nothing
/*critical section*/ //临界区
turn = 1; //退出区
/*remainder section*/ //剩余区
}while(0)
//进程P1
do{
while(turn != 1); //进入区
/*critical section*/ //临界区
turn = 0; //退出区
/*remainder section*/ //剩余区
}while(0)
能保证同一时刻只有一个进程进入临界区,但却要求两个进程轮流交替访问(故存在依赖)临界区,不满足空闲让进(若P0停在while判断或者之前,P1却无法进入临界区) 和 有限等待(P0阻塞,P1永远被阻止)!
- 版本二
enum boolean(false = 0;ture = 1);
boolean flag = {0,0}; //两个元素初始化为flase
//P0
...
do{
flag[0] = ture; //先写这句话则保证了互斥;若放在while后面,假设两个进程一开始都是flase,则不互斥
while (flag[1]); //判断对方是否在区内,不是则进入区;是则等待,一直循环 do nothing
/*critical section*/
flag[0] = false; //退出区
/*remainder section*/
}while(1)
...
//P1
...
do{
flag[1] = true;
while(flag[0]);
/*等待时do nothing*/
/*critical section*/
flag[1] = false;
/*remainder section*/
}while(1)
...
避免了两个进程轮流进入临界区,但存在两个进程都进不了临界区的可能性(若一开始都是ture则会发生死锁),不满足空闲让进和有限等待!
- 版本三
//P0
...
do{
flag[0] = ture;
while (flag[1]){
flag[0] = false; //暂时把自己置为flase,打破死锁
delay; //加一些延迟
flag[0] = ture;
} //可能出现活锁,无太大推进
/*critical section*/
flag[0] = false; //退出区
/*remainder section*/
}while(1)
...
//P1
...
do{
flag[1] = true;
while(flag[0]){
flag[1] = false;
delay; //加一些延迟
flag[1] = ture;
}
/*critical section*/
flag[1] = false;
/*remainder section*/
}while(1)
...
打破死锁,但是可能会出现活锁
- 最后一个版本-Dekker算法
boolean flag[2];
int turn;
void main()
{
flag[0] = false;
flag[1] = false;
turn = 1;
cobegin //=parbegin
P0();P1();
coend //=parend
}
void P0()
{
while (ture)
{
flag[0] = ture;
while(flag[1])
{
if(turn == 1)
{
flag[0] = false;
while(turn == 1) //do nothing
flag[0] = ture;
}
}
/*critical section*/
turn = 1;
flag[0] = false;
/*remainder section*/
}
}
void P1()
{
while (ture)
{
flag[1] = ture;
while(flag[0])
{
if(turn == 0)
{
flag[1] = false;
while(turn == 0) //do nothing
flag[1] = ture;
}
}
/*critical section*/
turn = 0;
flag[1] = false;
/*remainder section*/
}
}
三、Peterson算法
boolean flag[2];
int turn;
void main()
{
flag[0] = false;
flag[1] = false;
cobegin //=parbegin
P0();P1();
coend //=parend
}
void P0()
{
while (ture)
{
flag[0] = ture;
turn = 1;
while(flag[1] && turn == 1) //do nothing
/*critical section*/
flag[0] = false;
/*remainder section*/
}
}
void P1()
{
while (ture)
{
flag[1] = ture;
turn = 0;
while(flag[0] && turn == 0) //do nothing
/*critical section*/
flag[1] = false;
/*remainder section*/
}
}
Peterson算法更加简洁!