##第五章同步
临界区问题
当一个进程在临界区内执行时,其他进程不允许在它们的临界区执行.
第一种
do {
进入区
临界区
退出区
剩余区
}while(true);
Peterson解决方案
//变量turn表示哪个进程可以进入临界区
//而数组flag表示哪个进程准备进入临界区
//j=1-i
int turn;
bool flag[2];//全局数组初始化为false
do{
flag[i]=true;
turn =j;
while(flag[j]&&turn ==j);
//临界区
flag[i]=false;
}while(true);
进程Pi,Pj进入临界区的条件为
Pi
flag[j]==false||turn==i;
Pj
flag[i]==false || turn ==j;
如果进程Pi第一次先执行,flag数组全部为0,turn设置为j 此时flag[j]==false 因此进程Pi进入临界区,如果Pi,Pj并发执行,假设Pi先执行,此时flag[i]为true而且turn为j 随后进程Pj执行 进而将turn 改为i 当再次切换至进程Pi时,进程Pi发现此时不满足turn等于j 进而Pi进入临界区.当Pi从剩余区离开时,flag[i]设为false此时Pj便可进入临界区
第二种
#define N 2
int turn;
bool flag[N];
void enter(int process)
{
int other;
other=1-process;
flag[process]=true;
turn=process;//!!!不同于第一种算法
while(turn==process&&flag[other]);
}
void leave(int process)
{
flag[peocess]=false;
}
对于第二种算法 假设Pi先执行,此时turn==1-Pi 不满足flag[other]==true因此Pi进入临界区, 如果Pi,Pj并发执行 假设Pi先执行执行到turn设为Pi时,CPU切换至Pj,随后Pj将turn改为Pj 当Pi再次执行时发现turn 不为Pi 进入临界区
总结
发现这两种算法最终进入临界区的都是先执行的
都满足如下三点:
1.互斥 如果一个进程在临界区执行,那么其它进程都不能进入其临界区
2.进步,如果没有进程在其临界区内执行,并且有进程需要进入临界区,那么只有那些不在剩余区执行的进程可以选择,即不在临界区的进程不能阻止另一个进程进入临界区.
3.有限等待.不得使进程无限期等待进入临界区