需要帮助理解 test_and_set 互斥锁的实现

Need help understanding implementation of mutex with test_and_set

Silberschatz、Galvin 和 Gagne 的操作系统原理一书对 test_and_set

的原子操作有以下实现
boolean test_and_set(boolean *target) {
    boolean rv = *target;
    *target = true;
    return rv;
}

他们声明了一个初始化为 0 的全局变量锁,并为每个进程使用了​​以下互斥量实现

do {
    while(test_and_set(&lock))
        ; // do nothing
        // critical section
    lock = false;
        // remainder section
} while(true);

现在,让我们考虑进程P0正在执行临界区而进程P1卡在while循环中的情况。考虑下面的执行顺序 then

//lock = true initially because P0 is in critical section
P1 boolean rv = *target; //rv = true, lock = true
//P0 now completed its critical section and is ready to leave the lock
P0 lock = false //rv = true, lock = false
P1 *target = true; //rv = true, lock = true
P1 return rv; // returns true

因此,进程P0或任何其他进程实际上永远无法进入临界区。 那么这个案例是怎么处理的呢?

你的描述是对的,这种情况会导致死锁。
但是您缺少的是 test_and_set 必须是 atomic 操作。这不是 test 后跟 set,而是执行两者的 独特 牢不可破的操作。

一般是处理器用一条指令实现的,1/禁止乱序执行,2/等待处理器的流水线和内存队列为空,3/读取寄存器中的内存,4/设置内存字。 read/write 内存不能中断,不会发生线程交换,并且禁止其他处理器访问内存。

在 risc 处理器上,有类似的机制。您首先执行一个特殊的加载来监视对内存的访问(通常称为 load locked),然后是一个特殊的存储,如果对内存位置(store conditional)进行了任何访问,该存储将失败。

这样一来,就可以确定在 test_and_set 期间只有一个线程可以访问内存,而您描述的情况不会发生。

//lock = true initially because P0 is in critical section
P1 boolean rv = *target; //rv = true, lock = true
//P0 now completed its critical section and is ready to leave the lock
// BUT P0 MUST WAIT THE COMPLETION OF THE TAS.
// NO THREAD SWAP CAN HAPPEN AND ACCESS TO *target IS LOCKED
// DELAYED UNTIL END OF TAS P0 lock = false //rv = true, lock = false
P1 *target = true; //rv = true, lock = true
P1 return rv; // returns true
//NOW WE CAN DO
P0 lock = false //rv = true, lock = false
// AND LOCK IS PROPERLY UNSET
// ON NEXT ITERATION OF THE SPINLOCK WHILE, P1 WILL GET IT.