以下代码旨在解决关键部分问题。鉴于有N个进程正在修改其关键部分中的公共数据结构。
这些是使用的数据结构:
boolean waiting[n];
boolean lock;
这是testAndSet()函数,假定由于硬件支持而原子执行。
boolean TestAndSet(boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv;
}
//以下代码可确保互斥
do {
waiting[i] = TRUE;
key = TRUE;
while (waiting[i] && key)
key = TestAndSet(&lock);
waiting[i] = FALSE; //what if I skip this??
// critical section
j = ( i + 1) % n ;
while((j != i) && ! waiting[j])
{
j = (j + 1) % n ;
}
if (j == i)
lock = FALSE;
else
waiting[j] = FALSE;
//remainder section
}while (TRUE);
答案 0 :(得分:2)
你真的需要在第一次之后缩进该行。
" //关键部分"以下的内容将解锁等待访问的下一个任务,或者在没有人等待时释放锁定。
如果你没有清除你的等待标志,那么已经拥有锁定的另一项任务(可能是围绕他们访问受保护存储器运行相同的代码)会认为你还在等待并将清除你的等待标志让你运行(假设你正坐在循环中,检查TestAndSet,这是你的wait标志为真的唯一地方)。它保持锁定标志设置,因为它只是有效地将锁定传递给你。但是,如果您的代码实际上已经从那一点开始而没有设置值false,那么您无法在不将等待标志设置为True的情况下返回TestAndSet,并且由于锁定也保持为true,那么此任务可以& #39; t运行,其他任务没有运行,因为下一个任务没有得到批准(或者锁定没有设置为false),整个系统现在都是搞砸了。
答案 1 :(得分:0)
如果你跳过' ... = FALSE'这意味着你仍然在等待第一个while循环(对于特定的i)获取锁定(临界区)并且会破坏"循环的逻辑"访问第二个while循环中的临界区。
答案 2 :(得分:0)
消除那条线可能会破坏整个事情。它上面的两行是一个while
循环,它可以在两个条件中的一个上终止 - waiting[i]
变为假,或key
变为假(或者两者同时"同时&# 34)。如果循环由于key
为假而终止,那么waiting[i]
可能仍然是真的,所以你会进入一个你同时持有锁并同时认为你还在等待锁的情况。可能违反了后续while
循环的前提条件......
答案 3 :(得分:0)
我想我明白了。整个混乱是由do while()循环创建的,它包含整个代码。而不是这个做while()的东西,如果这些就像某个函数代表一个过程,如
function(int i)
{
waiting[i] = TRUE;
key = TRUE;
while (waiting[i] && key)
key = TestAndSet(&lock);
waiting[i] = FALSE; //what if I skip this??
// critical section
j = ( i + 1) % n ;
while((j != i) && ! waiting[j])
{
j = (j + 1) % n ;
}
if (j == i)
lock = FALSE;
else
waiting[j] = FALSE;
//remainder section
}
假设一个函数在i = 3的情况下被调用(比如过程i3。对于N = 5)。并且此过程i3永远不会再次执行,然后不设置等待[3] = false将最终陷入死锁状态。由于进程i4可能认为进程i3想要运行,因此最终会设置waiting [3] = false并且不释放锁