4

请看下面的伪代码:

boolean blocked[2];
int turn;
void P(int id) {
      while(true) {
             blocked[id] = true;
             while(turn != id) {
                    while(blocked[1-id])
                    /* do nothing */;
                    turn = id;
             }
             /* critical section */
             blocked[id] = false;
             /* remainder */
      }
}
void main() {
      blocked[0] = false;
      blocked[1] = false;
      turn = 0;
      parbegin(P(0), P(1)); //RUN P0 and P1 parallel
}

我认为可以使用上面的代码实现一个简单的互斥解决方案。但它不起作用。有谁知道为什么?

任何帮助将不胜感激!

4

6 回答 6

5

由于以下原因,不能保证互斥在此示例中:

我们从以下情况开始:

blocked = {false, false};
turn = 0;

P1 现在执行,并跳过

  blocked[id] = false; // Not yet executed.

现在的情况是:

blocked {false, true}
turn = 0;

现在 P0 执行。它通过第二个 while 循环,准备执行临界区。并且当 P1 执行时,它会将 turn 设置为 1,并且也准备好执行临界区。

顺便说一句,这种方法最初是由 Hyman 发明的。他于 1966 年将其发送给 ACM 通讯

于 2009-05-18T09:06:11.750 回答
2

由于以下原因,不能保证互斥在此示例中:

我们从以下情况开始:

turn= 1;
blocked = {false, false};

执行如下:

P0: while (true) {
P0:   blocked[0] = true;
P0:   while (turn != 0) {
P0:     while (blocked[1]) {
P0:     }
P1: while (true) {
P1:   blocked[1] = true;
P1:   while (turn != 1) {
P1:   }
P1:   criticalSection(P1);
P0:     turn = 0;
P0:   while (turn != 0)
P0:   }
P0:   critcalSection(P0);
于 2009-12-07T20:14:29.540 回答
0

这是作业,还是一些嵌入式平台?有什么理由不能使用 pthread 或 Win32(相关的)同步原语吗?

于 2009-01-04T22:02:55.217 回答
-1

也许你需要将blocked和turn声明为volatile,但是不指定编程语言就无从得知。

于 2009-01-04T19:19:06.310 回答
-1

并发不能这样实现,尤其是在多处理器(或多核)环境中:不同的核/处理器有不同的缓存。这些缓存可能不一致。下面的伪代码可以按所示顺序执行,结果如下:

get blocked[0] -> false   // cpu 0
set blocked[0] = true     // cpu 1 (stored in CPU 1's L1 cache)
get blocked[0] -> false   // cpu 0 (retrieved from CPU 0's L1 cache)
get glocked[0] -> false   // cpu 2 (retrieved from main memory)

需要硬件知识来实现​​并发。

于 2009-01-04T20:03:57.017 回答
-1

编译器可能已经优化了“空”while 循环。将变量声明为 volatile 可能会有所帮助,但不能保证在多处理器系统上就足够了。

于 2009-01-04T20:40:33.807 回答