硬件方式实现互斥:
-
屏蔽中断: 利用“开/关中断指令” 实现(与原语实现方式相同)
…
关中断
临界区
开中断
…
优点:简单,高效;
缺点:不适用多处理机 (两个处理机,A,B:A中断后不会发生线程切换,但对B没有影响,这就会有两个进程在临界区的情况)
不适用于用户进程 (在中断运行在内核态) -
Test and Set指令
TSL指令用硬件实现,执行过程不允许被中断,只可以一气呵成
// false 表示临界区可以用(未上锁), true表示不能用(上锁)
bool TestAndSet(bool *lock){
bool old;
old = *lock;
*lock = true;//不管之前都上锁
return old;
}
while(TestAndSet(&lock));
临界区
lock=false;
lock = false; TSL返回false; while()循环不满足进入临界区,
lock = true; TSL返回true; while()满足一直等待
- exchange指令
swap(bool *a, bool *b){
bool temp;
temp = *a;
*a = *b;
*b = temp;
}
bool old;
while(old == true)
swap(&lock, &old);
临界区代码;
lock = false;
机器指令:
优点:实现简单,不用像软件方法检查有逻辑漏洞;使用多处理机系统
缺点:不满足让权等待,暂时无法进入临界区的进程会占用CPU,从而 Busy wating,忙等;
软件方法实现互斥
- 单标志法
int flag = 0;
p1 进程 p2 进程
while( flag ); while( !flag);
临界区 临界区
flag = 1; flag = 0;
…
一开始只允许1号进程进入临界区,能够访问临界区顺序:p1,p2,p1,p2…
不满足空闲让进:当p2先执行时
- 双标记先检查
bool flag[] = {false, false};//都能进入
p1 进程 p2 进程
- while( flag[2] ); 5. while(flag[1]);
- flag[1] = true; 6. flag[2] = true;
- 临界区 7. 临界区
- flag[1] = false; 8. flag[1] = false;
...... ........
当有中断:1->5->2->6->3->7 p1,p2都进入
- 双标记后检查
p1 进程 p2 进程
1, flag[1] = true; 5, flag[2] = true;
2. while( flag[2] ); 6. while(flag[1]);
3. 临界区 7. 临界区
4. flag[1] = false; 8. flag[1] = false;
...... ........
1,5,2,6 p1,p2都进不了
- Peterson算法
bool flag[] = {false, false};
int vis = 0;
p1:
1, flag[1] = true;
2, vis = 1;
3. while( flag[2] && vis);
4. 临界区
5. flag[1] = false;
p2:
6, flag[2] = true;
7, vis = 0;
8. while(flag[1] && !vis);
9. 临界区
10. flag[1] = false;
...... ........
满足空闲让进,忙则等待,有限等待,(不满足让权等待)