《操作系统概念》笔记--硬件同步与互斥锁

硬件同步

test_and_set()

boolean test_and_set(boolean *target){
    boolean rv = *target;
    *target = true;

    return rv;
}

先声明一个布尔变量lock,初始化为false。
当没有进程在临界区内时,lock为false, 当有进程在临界区内时,lock为true。
当一个进程想要进入临界区时,它会先调用test_and_set(),test_and_set()返回lock的原始值,并将lock赋值为true。
若返回值为false,则该进程可进入临界区
若返回值为true,则表示有进程在临界区,所以该进程需循环调用test_and_set(),直到没有进程在临界区内。
采用指令test_and_set的进程实现:

do{
    while(test_and_set(&lock));
    
    lock = false;
}while(true);

compare_and_swap()

int compare_and_swap(int *value, int expected, int new_value){
    int temp = *value;
    
    if(*value == expected)
        *value = new_value;
    
    return temp;
}

指令compare_and_swap()需要三个操作数。
首先声明一个全局布尔变量lock,初始化为0。
当临界区内有进程时,lock值为1,临界区内没有进程时,lock值为0
当一个进程需要进入临界区时,首先调用compare_and_swap(&lock, 0, 1),中间为期望值,最后面为新增值,返回lock原始值。
如果没有进程在临界区,lock值为0,调用之后,因为lock值等于期待值0,lock值变为1,并且返回0,于是进入临界区。
如果有进程在临界区,lock值为1,调用之后,lock值不等于期待值,返回值为1不等于0,于是循环调用等待。
采用指令compar_and_swap()的指令实现:

do{
    while(compare_and_swap(&lock, 0, 1) != 0);

    lock = 0;

}while(true);

满足有限等待

上述并不满足有限等待条件,下面实现满足有限等待的test_and_set()
进程共用的数据结构为:
boolean waiting[n]
boolean lock
这些结构初始化为false。
只有waiting[i] == false 或者 key == false时,进程pi才能进入临界区

do{

waiting[i] = true;
key = true;
while(waiting[i] && key)
    key = test_and_set(&lock);
waiting[i] = false;

//当队列中下一个进程wainting为true,时,表示要进入临界区,于是得到j
j = (i+1) % n;  
while((j!= i) && !waiting[j])
    j = (j+1)%n;

//把lock设为false或者把waiting[j]设为false,都能使j进程推出循环等待,进入临界区。
if(j == i)
    lock = false;
else
    waiting[j] = false;

}while(true);

当wainting[i] == true时,代表该进程想进入临界区。
key初始化为true,当临界区没有进程时,lock为false,调用test_and_set,key设为false,lock设为true,该进程进入临界区。
当临界区有进程时,lock为true,key一直为true,于是循环调用等待,直到进程离开临界区。
当该进程离开临界区时,wainting[i]设为false,表示不想进入临界区。

#互斥锁
每个互斥锁有一个布尔变量available,它的值表示锁是否可用。
如果琐是可用的,那么调用acquire()会成功,并且锁不再可用
当一个进程试图获取不可用的锁时,它会阻塞,知道锁被释放。

acquire(){
    while (!available);
    
    availablle = false;
}
release(){
    available = true;
}

互斥锁的缺点是需要忙等待。

当有一个进程在临界区中,任何其他进程在进入临界区时必须连续循环地调用acquire()。

** 考虑如何使用原子硬件指令实现互斥锁。假设互斥锁的结构如下:

typedef struct{
    int available;
}lock;

当available为0时,表示锁可用;当available为1时,表示锁不可用。通过这个struct,说明如何采用指令test_and_set()和compare_and_swap()来实现如下函数,一定包括任何可能必要的初始化:

  • void acquire(lock *mutex)
void acquire(lock *mutex){
    while(test_and_set(*mutex.available));
}
void acquire(lock *mutex){
    while(compare_and_swap(*mutex.available, 0, 1) != 0);
}
  • void release(lock *mutex)
void release(lock *mutex){
    *mutex.available = 0;
}
发布了63 篇原创文章 · 获赞 8 · 访问量 7207

猜你喜欢

转载自blog.csdn.net/s1547156325/article/details/103794125
今日推荐