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

为何SPIN在此场景下无法检测非进展循环?

SPIN非进展循环检测异常原因分析

初始代码与检测结果

原始Promela代码如下:

byte x=2;
active proctype A() {
  do  
  :: x = 3-x
  od  
}
active proctype B() {
  do  
  :: x = 3-x 
  od                                                                                                                          
}

经gcc -DNP -o my pan.c编译后,执行./my -l,SPIN可检测到非进展循环。

第一次修改后的检测结果

将进程A修改为:

active proctype A() {
  do  
  :: x = 3-x; progress: skip
  od  
}
  • 执行./my -l -f(-f表示CPU时间片公平分配)时,非进展循环消失;
  • 执行./my -l时,仍可检测到该循环。

第二次修改后的检测结果

仅将进程A修改为:

active proctype A() {
progress:
  do  
  :: x = 3-x
  od  
}

此时./my -l与./my -l -f两种模式均无法检测到非进展循环。

用户猜测

  • 猜测1:SPIN存在bug
  • 猜测2:两个进程共用同一FSM(及状态),而修改后将该共用FSM的整个状态标记为始终处于进展中

FSM图佐证

通过./my -D生成的FSM图显示仅存在一个状态S2:

digraph p_A {
size="8,10";
  GT [shape=box,style=dotted,label="A"];
  GT -> S2;
        S2 -> S2  [color=black,style=bold,label="x = (3-x)"];
  S2 [color=green,style=bold];
digraph p_B {
size="8,10";
  GT [shape=box,style=dotted,label="B"];
  GT -> S2;
        S2 -> S2  [color=black,style=bold,label="x = (3-x)"];

原因解析

你的第二个猜测是正确的,并非SPIN的bug。

SPIN中progress:标签的作用是标记进程当前所处的状态属于进展状态——只要进程处于带有该标签的状态,就会被判定为正在推进系统的进展,不会被计入非进展循环的判定逻辑。

在第二次修改中,你将progress:标签放在了do循环的外部,意味着进程A从启动后就直接进入了带有progress:标记的状态,并且整个循环过程中始终处于这个状态。结合FSM图可以看到,两个进程的状态机完全重合(共用同一状态S2),SPIN的状态合并机制会将结构完全一致的进程状态机合并为同一个。这就导致只要其中一个进程的状态被标记为progress,整个共用状态就会被判定为进展状态。

当系统处于这个状态时,无论调度哪个进程执行,都会被认为是在推进进展,自然不会检测到非进展循环——因为非进展循环的判定条件是:存在一个循环路径,其中所有进程都没有产生任何进展(即都不在progress标记的状态,且没有执行任何能推进系统的动作)。

而第一次修改中,progress:标签放在了循环体的动作之后,只有当进程A执行完x=3-x后才会进入进展状态。在非公平调度模式下(./my -l),SPIN可能会一直调度进程B执行,此时进程A始终处于未到达progress:标记的状态,进程B也没有任何progress标记,因此系统会被判定为陷入非进展循环;而公平调度模式(-f)会保证每个进程都有机会执行,进程A能周期性进入progress状态,打破非进展循环的判定条件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:10:33