【问题标题】:Mutual Exclusion Problem互斥问题
【发布时间】:2009-01-04 19:06:47
【问题描述】:

请看下面的伪代码:

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
}

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

任何帮助将不胜感激!

【问题讨论】:

  • 请发布真实代码而不是伪代码,并指定语言。多线程容易出现非常细微的错误 - 查看准确代码至关重要。
  • 我之前犯过这个错误(发布psudo),在贴出真实代码的过程中发现了问题。所以拜托,真正的代码。
  • 另外,你怎么知道它不起作用?
  • 不工作是指...?
  • 该程序是用 C 语言编写的,我无法发布源代码,因为它真的很长。问题是,在某些时候,两个过程都访问了关键部分......

标签: mutex


【解决方案1】:

互斥在此示例中无法保证,原因如下:

我们从以下情况开始:

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 通讯

【讨论】:

    【解决方案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);
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

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

          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)
          

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

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-08-05
              • 1970-01-01
              相关资源
              最近更新 更多