实现进程互斥的硬件方法

实现进程互斥的硬件方法

中断禁用

单处理器系统中进程在进入临界区前禁用中断,离开临界区后启用中断,这样保证进程在临界区时不会被打断,不会被抢占

while (true){
    //禁用中断
    //临界区
    //启用中断
    //其他部分
}

缺点:
影响效率,所有其他进程都等待在临界区的进程,可能让其他进程处于饥饿状态
不能用于多处理器机器上

TestSet指令

原子操作机器指令,对传进来的值更新为1,并返回旧的值。
C语言版本的伪代码,只用来解释TestSet指令的逻辑,真实实现是原子机器指令

 #define LOCKED 1

int TestAndSet(int* lockPtr) {
    int oldValue;
     
    // -- Start of atomic segment --
    // This should be interpreted as pseudocode for illustrative purposes only.
    // Traditional compilation of this code will not guarantee atomicity, the
    // use of shared memory (i.e., non-cached values), protection from compiler
    // optimizations, or other required properties.
    oldValue = *lockPtr;
    *lockPtr = LOCKED;
    // -- End of atomic segment --

    return oldValue;
}

我们可以给予TestSet指令来实现对临界区加锁解锁的操作


volatile int lock = 0;
 void Critical() {
     while (TestAndSet(&lock) == 1); // add lock
     critical section // only one process can be in this section at a time
     lock = 0 // release lock when finished with the critical section
 }

在上述代码中,lock有0跟1两个值,初始化为0,那么第一个执行到while (TestAndSet(&lock) == 1);的进程A会跳过while循环,因为TestAndSet返回lock的旧值0,然后lock就成了1,进程A进入临界区,此时如果进程B也执行到while循环,TestAndSet会一直返回1,一直循环下去。此时如果进程A已经离开临界区,把lock设为了0,那么在等待的进程B会跳出while循环,进入临界区,这就实现了对临界区的加锁解锁操作,保证了同一时间只有一个进程会进入临界区。
上述过程对多个进程也同样适用,只有lock=0时第一个执行到while循环的进程能进入临界区,其他进程的lock一直会是1,知道lock被重新设置为0.

这都要归功于TestAndSet的原子操作,如果其不是原子操作,可能会两个进程在*lockPtr=0时都执行了oldValue = *lockPtr; 然后再执行*lockPtr = LOCKED;此时两个进程都会返回0,导致两个进程同时进入临界区

优点:适用于单处理器或共享内存的多处理器上的任意数量的进程
简单且易证明
支持多个临界区,每个临界区有自己的变量
缺点:
while循环等待时一直消耗CPU时间,存在忙等待(busy-waiting)问题
可能饥饿,一个进程离开临界区而多个进程在等待进入临界区时,选择哪个进程进入是随机的,因为有的进程可能会一直无法进入临界区
可能死锁,进程P1进入临界区,然后P1被中断并把CPU让给等级更高的P2进程,P2进程会一直忙等待,无法进入临界区,而此时P1不会从其他状态转换为运行态,因为P1等级比P2低,P1在等待P2离开运行态,而P2一直在等P1离开临界区,形成死锁
https://www.bilibili.com/video/av6538245?p=62
https://en.wikipedia.org/wiki/Test-and-set

Exchange指令

原子操作机器指令,伪代码如下

void exchange(int * register,int *memory){
    int temp;
    temp=*memory;
    *memory=*register;
    *register=temp;
}

用exchange指令实现互斥

int bolt;
void Process(int i){
    while (true){
        int keyi=1;
        do exchange(keyi,bolt)
        while (keyi!=0);
        //临界区代码
        bolt=0
        //其他部分
    }
}

假设一共有N个进程,i对应的是0,1,。。。N-1,那么可以保证任意时刻bolt+key0+key1+…+keyN-1==N恒为True,如果bolt=0,则无进程进入临界区,其他时候任意一个进程的keyi=0,bolt=1,表示i进程进入临界区,其他进程在等待

优点: 如TestSet指令
缺点: 如TestSet指令

Compare and Swap指令(CAS指令)

类似,不再详述
https://en.wikipedia.org/wiki/Compare-and-swap

发布了51 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_36267931/article/details/103196271