我们在软件同步机制里讲的两个例子,都是在落锁和判断之间发生中断,乃至导致无法实现互斥的进入临界区,那么,我们是不是可以在这个期间不允许发生中断呢?这个就需要用到硬件了,下面我们就一起来看一下。
3.1 关中断
这个方法就非常之霸气了,进程在落锁和判断之间不是有可能会发生中断么,那么我在开始测试之前关闭中断(OS内核不响应中断信号),到测试并上锁之后在打开中断。这样可以保证两个操作之间的连续性,保证临界资源的互斥访问。
但是关中断也必然会存在许多缺点:1.滥用关中断的权利可能导致严重后果;2.关中断时间过长会影响系统的并发性,直接的影响系统的资源利用率;3.关中断无法适应多CPU系统(多CPU系统不在本文的讨论范围内)
3.2 测试并建立(Test-and-Set, TS)指令
我们使用关中断来解决落锁和判断之间不允许响应中断,但是我们如果把这两个执行变成一条指令呢,这样是不是就可以保证中断不会再落锁和判断之间被响应?
我们可以借助一条硬件指令-----“测试并建立”指令TS(Test-and-Set),来实现临界资源的互斥访问。TS指令的一般性描述如下:
//TS指令
boolean TS(boolean *lock){
if(*lock == false){
*lock = true;
return true;
}else{
return false;
}
}
//内存中保存的锁的值
boolean lock;
lock = false; //临界区可以进入
//进程P1,P2,P3...Pn
process Pi{
//...
while(!TS(&lock));//循环请求锁
临界区;
lock = false;//解锁,归还临界资源
}
我们可以把TS指令看成上面的TS函数的执行过程,其执行过程是不可分割的,即是一条原语。当lock的值为false时,表示临界资源空闲,当lock的值为true时,表示该资源正在被使用。
使用TS指令来管理临界区时,需要为每个临界资源设置一个布尔变量lock。当有进程需要进入临界区时,需要先用TS指令测试临界区对应的那把“锁”,如果返回true,临界区空闲,可以进入,并落锁,阻止别的进程再进入临界区;如果TS返回false,则必须要循环请求,直到TS返回的值变为true。
3.3 对换指令
该指令也称为swap指令,用于交换两个字的内容,其处理过程描述如下:
void swap(boolean *a, boolean *b){
boolean tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
//内存中保存的锁的值
boolean lock;
lock = false; //临界区可以进入
//进程P1,P2,P3...Pn
process Pi{
//...
boolean key = true;
do{
swap(&lock, &key);
}while(key != false)//循环请求锁
临界区;
lock = false;//解锁,归还临界资源
}
Swap指令和TS指令类似,也需要为每个临界资源设置一个布尔变量lock,不同的在进程中使用一个局部变量Key字段去替换出lock中的值,通过判断key的值就可以判断临界资源是否空闲。










