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/
这个问题的测验