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 }
}
仅当数量大于“ int”大小的进程执行while循环的检查条件而不是L = 1(即需要先占)时,才会发生溢出。
但是,当L为1时,该过程将在while循环中重复进行-没有溢出,因为在每次递增到L后,L再次等于1。
选项(b)是选项(a)的最佳选择。
资料来源:http://www.geeksforgeeks.org/operating-systems-set-17/
这个问题的测验