📜  门|门CS 2012 |第 30 题

📅  最后修改于: 2021-09-25 06:23:27             🧑  作者: Mango

Fetch_And_Add(X,i) 是一个原子性的 Read-Modify-Write 指令,它读取内存位置 X 的值,将其增加值 i,并返回 X 的旧值。它在下面显示的伪代码中用于实现一个忙等待锁。 L是初始化为0的无符号整数共享变量。0的值对应锁可用,而任何非零值对应锁不可用。

AcquireLock(L){
         while (Fetch_And_Add(L,1))
               L = 1;
   }
  ReleaseLock(L){
         L = 0;
   }

这个实现
(A)失败,因为 L 可能溢出
(B)失败,因为当锁实际可用时 L 可以采用非零值
(C)工作正常,但可能会使某些进程挨饿
(D) 在没有饥饿的情况下正常工作答案:(乙)
说明:仔细看看下面的 while 循环。

while (Fetch_And_Add(L,1))
               L = 1;  // A waiting process 
                       // can be here just after 
                       // the lock is released, 
                       // and can make L = 1.

考虑一个进程刚刚释放锁并使 L = 0 的情况。让另一个进程等待锁,意味着执行 AcquireLock()函数。在 L 被设为 0 之后,让等待进程执行 L = 1 行。现在,锁可用并且 L = 1。由于 L 是 1,等待进程(以及任何其他未来的进程)不能出来while 循环的。

上述问题可以通过将 AcuireLock() 更改为以下来解决。

AcquireLock(L){
         while (Fetch_And_Add(L,1))
         { // Do Nothing }
   }

只有当比 ‘int’ 的大小多的进程数执行 while 循环的检查条件而不是 L = 1,即需要抢占时,才会发生溢出。
但是当 L 为 1 时,该过程在 while 循环中重复——没有溢出,因为在每次递增 L 后,L 再次等于 1。
选项 (b) 是选项 (a) 的最佳选择。

来源:http://www.geeksforgeeks.org/operating-systems-set-17/

这个问题的测验