以下问题已在 GATE 2012 CS 考试中提出。
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) 在没有饥饿的情况下正常工作
答案 (B)
仔细看看下面的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 }
}
请参阅 GATE Corner 了解所有往年论文/解决方案/解释、教学大纲、重要日期、笔记等。