最近在准备推免的面试把王道的进程这一章拿出来做了一下,收获挺多的,写个文章总结下
2.3进程同步
访问临界资源过程
do{
entry section;//进入区 设置访问临界区标志
critical section;//临界区 访问临界资源
exit section;//退出区 将访问临界区标志清除
remainder section;//剩余区
}while(true)
软件实现临界区互斥
1.单标志法
单标志法主要问题是对临界区资源的访问各个进程需要交替进行,如果一个进程完成后,及时临界区可以访问,另一个进程也无法进入。这就违背了“空闲让进”原则
P0进程:
while(turn!=0);
critical section;
turn=1;
remainder section;
p1进程:
while(turn!=1);
critical section;
turn =0;
remainder section;
2.双标志法先检查
先判断对方是否在访问临界区,然后再决定自己是否进入,它都问题是如果按照1 2 3 4的顺序执行的话,双法都进入临界区,这样就违背了忙则等待的原则
pi进程
while(flag[j));//1
flag[i]=TRUE;//3
critical section;
flag[i]=FALSE;
remainder section;
pj进程
while(flag[i]);//2
flag[j]=TRUE;//4
critical section;
flag[j]=FALSE;
remainder section;
3.双标志后检查法
先将临界区设置为自己的,再判断对方是否访问,这个方法的问题是如果按照1 2 3 4 执行的话,3,4 都会永远处于真,这样会导致饥饿问题
pi进程
flag[i]=TRUE;//1
while(flag[j]);//3
critical section;
flag[i]=FALSE;
remainder section;
pj进程
flag[j]=TRUE;//2
while(flag[i]);//4
critical section;
flag[j]=FALSE:
remainder section;
4.Peterson‘s Algorithm
该算法的核心是通过增加turn让后执行的turn赋值语句,决定谁先进入临界区
pi进程
flag[i]=TRUE;//1
turn=j;
while(flag[j]&&turn==j);//3
critical section;
flag[i]=FALSE;
remainder section;
pj进程
flag[j]=TRUE;//2
turn=i;
while(flag[i]&&turn==i);//4
critical section;
flag[j]=FALSE:
remainder section;
硬件实现方法
1.中断屏蔽方法
因为cpu只有在发生中断的时候才能进行进程切换,因此关中断就可以保证临界区资源顺利访问
2.硬件指令
TestAndSet指令
Swap 指令
优点:适用于任意数目的进程,不管是单处理机还是多处理机:简单,容易验证其正确性,可以支持进程内有多个临界区,只需为没给临界区设立一个信号量即可。
缺点:进程等待进入临界区时需要消耗处理机时间,不能实现让权等待,从等待进入进程中随机选择一个进入临界区,有的进程可能一直选不上,从而导致”饥饿“现象。
信号量
信号量只能被两个标准的原语wait(S)和signal(S)来访问,也可被记错P/V
1.整型信号量
一个用于表示资源数目的整型量S,wait和signal操作可描述为下方,问题是wait中如果S<=0,就会不断尝试,因此该机制并未遵循“让权等待”原则
wait(S){
while(S<=0);
S=S-1;
}
signal(S){
S=S+1;
}
2.记录型信号量
记录型信号量通过一个记录进程的队列来避免重复尝试。
记录型信号量数据结构
typedef struct{
int value;
struct process *L;
}semaphore;
void wait(semaphore S){
S.value--;
if(S.value<0){
block(S.L);
}
}
void signal(semaphore S)
S.value++;
if(S.value<=0){