You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何BACI监视器函数无法共享变量/条件?并发程序死锁排查

并发程序死锁问题排查(基于Ben-Ari Concurrent Interpreter)

我正在编写一个并发程序,要求按顺序打印字母A和B。以下程序语法正确且可编译,但每次运行都会发生死锁:

monitor simple_monitor { 
  int isAPrinted = 0;
  condition B_wait;

  void monitorA() { 
    isAPrinted = 1;
    cout << "A: Value of isAPrinted is now " << isAPrinted << endl;
    signalc (B_wait);
  } 

  void monitorB() {
   cout << "B: Value of isAPrinted is now " << isAPrinted << endl;
   if ( !isAPrinted ) 
      waitc( B_wait ); 
  }
} 


int main() { cobegin { monitorA(); monitorB();  } }

具体错误输出如下:

Executing PCODE ...
A: Value of isAPrinted is now 1
B: Value of isAPrinted is now 0

BACI System: Command-line PCODE Interpreter in Java, 09:46  05 Nov 2007
Execution of process 2 aborted at loc 23
>>>Deadlock in process 2
 Process       Active Suspend  PC    xpc   atomic
 0 main             0  6000    38     0     0
 1 monitorA         0    -1     0     0     0
 2 monitorB         0  2607    23     0     0
...

当monitorB先运行时,本应等待B_wait,待monitorA执行signalc(B_wait)后唤醒,但实际未被唤醒;当monitorA先运行时,本应将isAPrinted设为1,使monitorB无需等待,但monitorB运行时isAPrinted仍为0,仿佛两个函数处于独立的执行上下文。我使用的是javabaci(Ben-Ari Concurrent Interpreter,一款大学操作系统课程教学用的并发解释器),类似示例程序可正常运行,请问问题出在哪里?


问题根源

你在cobegin中直接调用监视器成员函数monitorA()和monitorB(),但Ben-Ari的监视器语法要求必须通过监视器对象调用成员函数。当前写法下,两个函数并未进入监视器的临界区,共享变量isAPrinted不受互斥机制保护,导致数据不一致、信号操作无效,最终引发死锁。

修复方案

  1. 实例化监视器对象;
  2. 通过对象调用成员函数;
  3. 将monitorB中的if条件判断改为while——这是监视器编程的标准实践,可避免虚假唤醒导致的逻辑错误。

修复后的代码:

monitor simple_monitor { 
  int isAPrinted = 0;
  condition B_wait;

  void monitorA() { 
    isAPrinted = 1;
    cout << "A: Value of isAPrinted is now " << isAPrinted << endl;
    signalc (B_wait);
  } 

  void monitorB() {
    cout << "B: Value of isAPrinted is now " << isAPrinted << endl;
    // 用while循环检查条件,处理虚假唤醒
    while ( !isAPrinted ) 
      waitc( B_wait ); 
  }
} 

int main() { 
  // 实例化监视器对象
  simple_monitor m;
  // 通过对象调用成员函数,确保进入监视器临界区
  cobegin { m.monitorA(); m.monitorB();  } 
}

修复说明

  • 实例化监视器对象后,所有成员函数调用都会进入互斥临界区,保证isAPrinted的读写操作原子性;
  • signalc和waitc会正确关联到该对象的条件变量B_wait,唤醒等待的进程;
  • while循环替代if,可避免进程被意外唤醒时跳过条件检查,确保逻辑正确性。

内容的提问来源于stack exchange,提问作者Mark Peschel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 15:49:56