如果我在下面的代码片段中跳过 waiting[i] = false 会发生什么?
What will happen if I skip waiting[i] = false In the following snippet of code?
下面的代码是为了解决临界区问题而设计的。假设有 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);
如果您跳过“... = FALSE”行,这意味着您仍在第一个 while 循环(对于特定 i)中等待获取锁(临界区),并且会破坏 "round robin" 在第二个 while 循环中访问临界区。
删除那条线可能会破坏整个事情。它上面的两行是一个 while
循环,它可能会在两种情况之一中终止——要么 waiting[i]
变成假,要么 key
变成假(或者两者都 "simultaneously") .如果循环由于 key
为假而终止,那么 waiting[i]
可能仍然为真,因此您将进入一种情况,您既持有锁又同时认为您仍在等待锁,这可能违反了后续 while
循环的先决条件...
你确实需要在第一个 while 之后缩进该行。
"// critical section" 下面的内容将解锁下一个等待访问的任务,或者如果没有人在等待则释放锁。
如果您不清除您的等待标志,那么另一个已经获得锁的任务(大概 运行使用相同的代码来访问受保护的内存)会认为您仍在等待并且会清除您的等待标志以允许您 运行(假设您正处于循环中,检查 TestAndSet,这是您的等待标志唯一为真的地方)。它保持锁定标志设置,因为它只是有效地将锁定传递给您。但是,如果您的代码实际上已经从该点继续前进而没有将值设置为 false,那么如果您不将等待标志设置为 True 就无法返回到 TestAndSet,并且由于 lock 也保留为 true,因此该任务无法执行运行,其他任务没有 运行ning,因为下一个任务没有得到批准(或者锁定没有设置为 false),整个系统现在都崩溃了向上。
我想我明白了。整个混乱是由包含整个代码的 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 永远不会再次执行然后不设置 waiting[3]=false 将以死锁情况结束。由于进程 i4 可能认为进程 i3 想要 运行 因此它将通过设置 waiting[3] = false 并且不释放锁来结束
下面的代码是为了解决临界区问题而设计的。假设有 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);
如果您跳过“... = FALSE”行,这意味着您仍在第一个 while 循环(对于特定 i)中等待获取锁(临界区),并且会破坏 "round robin" 在第二个 while 循环中访问临界区。
删除那条线可能会破坏整个事情。它上面的两行是一个 while
循环,它可能会在两种情况之一中终止——要么 waiting[i]
变成假,要么 key
变成假(或者两者都 "simultaneously") .如果循环由于 key
为假而终止,那么 waiting[i]
可能仍然为真,因此您将进入一种情况,您既持有锁又同时认为您仍在等待锁,这可能违反了后续 while
循环的先决条件...
你确实需要在第一个 while 之后缩进该行。
"// critical section" 下面的内容将解锁下一个等待访问的任务,或者如果没有人在等待则释放锁。
如果您不清除您的等待标志,那么另一个已经获得锁的任务(大概 运行使用相同的代码来访问受保护的内存)会认为您仍在等待并且会清除您的等待标志以允许您 运行(假设您正处于循环中,检查 TestAndSet,这是您的等待标志唯一为真的地方)。它保持锁定标志设置,因为它只是有效地将锁定传递给您。但是,如果您的代码实际上已经从该点继续前进而没有将值设置为 false,那么如果您不将等待标志设置为 True 就无法返回到 TestAndSet,并且由于 lock 也保留为 true,因此该任务无法执行运行,其他任务没有 运行ning,因为下一个任务没有得到批准(或者锁定没有设置为 false),整个系统现在都崩溃了向上。
我想我明白了。整个混乱是由包含整个代码的 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 永远不会再次执行然后不设置 waiting[3]=false 将以死锁情况结束。由于进程 i4 可能认为进程 i3 想要 运行 因此它将通过设置 waiting[3] = false 并且不释放锁来结束