这里,http://spinroot.com/spin/Man/Manual.html,写道:
在Promela中还有另一种避免测试和设置的方法 问题:原子序列。通过为一系列语句添加前缀 用大括号括起来,用户可以指示关键字atomic 该序列将作为一个不可分割的单位执行, 与任何其他进程不交错。 导致运行时错误 如果除第一个语句之外的任何语句都阻塞在原子语中 序列即可。这就是我们如何使用原子序列来保护原子序列 在前面的例子中并发访问全局变量状态。
在这里,http://spinroot.com/spin/Man/atomic.html,写道:
如果原子序列中的任何语句阻塞,原子性就会丢失 如果原子序列中的任何语句阻塞,原子性就会丢失, 然后允许其他进程开始执行语句。 当被阻止的语句再次变为可执行时,执行 原子序列可以随时恢复,但不一定 立即。在进程可以恢复原子执行之前 在序列的其余部分,该过程必须首先与所有人竞争 系统中的其他活动过程重新获得控制权,即它 必须首先安排执行。
那么,真实的是什么?从第一次引用中我们可以了解到它不允许在原子中阻塞(不是第一个语句)
从第二次引用中我们了解到可以在原子上阻止它。你只是失去了原子性,就是这样。
答案 0 :(得分:0)
矛盾文档:
我的猜测是矛盾仅仅是文档部分内容未被更新以反映多年来在 Spin 中发生的变化的结果。
事实上,在{strong> Spin v的release notes中。 2.0 我们可以找到以下文本(重点是我的):
2.3.1阻止原子序列
到目前为止,如果包含原子序列,则认为是错误 任何可能阻止序列执行的陈述。这个 造成了很多混乱,并且不必要地使建模变得复杂。开始 使用Spin版本2,阻止原子序列是合法的。如果一个 在原子序列块内处理,控制转移 对另一个过程不确定。如果声明以后 变得可执行,控制可以返回进程和原子 继续执行序列的其余部分。
语义的这种变化使得模型相对容易 实例,控制不从一个进程传递到的协同例程 另一个,除非正在运行的进程阻止。
Promela的原子声明:
在当前版本的 Promela / Spin 中,存在两个原子序列:
docs,重点是我的:
<强>描述强>
如果括号中包含一系列语句并以关键字atomic 作为前缀,则表示该序列将作为一个不可分割的单元执行,与其他进程不交错。在流程执行的交错中,从执行原子序列的第一个语句到最后一个语句完成之前,没有其他进程可以执行语句。序列可以包含任意Promela语句,并且可能是非确定性的。
如果原子序列中的任何语句阻塞,原子性丢失,然后允许其他进程开始执行语句。当被阻止的语句再次变为可执行时,原子序列的执行可以是随时恢复,但不一定立即恢复。在进程可以恢复序列其余部分的原子执行之前,进程必须首先与系统中的所有其他活动进程竞争以重新获得控制权,即必须首先将其安排执行。
[...]
docs,重点是我的:
说明
执行 d_step 序列,好像它是一个不可分割的语句。它与原子序列相当,但它在以下三点上与这些序列不同:
- 不允许goto跳入或跳出d_step序列。
- 确定性地执行序列。如果存在非确定性,则以固定和确定的方式解决,例如,始终在每个选择和重复结构中选择第一个真正的保护。
- 如果序列中任何语句的执行都可以阻止,则会出错。这意味着,例如,在大多数情况下,发送和接收语句不能在d_step序列中使用。
[...]
当然,实际上可以使用简单的 Promela示例来测试此行为。
测试1:使用atomic {}
采用以下 Promela模型,其中两个进程pippo
和pluto
执行atomic {}
指令序列,最多10
次。每个进程在开始执行原子序列时将其唯一_pid
保存在全局变量p
内,然后检查flag
变量:
flag
是true
,pippo
可以执行但pluto
不能执行,因此pluto
应该暂时失去原子性(在某些执行跟踪中)flag
是false
,pluto
可以执行但pippo
不能执行,因此pippo
应该暂时失去原子性(在某些执行跟踪中)我们通过在assert(p == _pid)
中的原子序列末尾添加pippo
指令来检查最新案例。如果条件未被违反,则意味着没有执行pippo
从原子序列中失去原子性而pluto
开始执行。否则,我们证明atomic {}
bool flag;
pid p;
active proctype pippo ()
{
byte i;
do
:: i < 10 ->
atomic {
true ->
p = _pid;
flag; /* executable only if flag is true */
printf("pippo unblocked\n");
flag = !flag;
assert(p == _pid);
};
i++;
:: else -> break;
od;
};
active proctype pluto ()
{
byte i;
do
:: i < 10 ->
atomic {
true ->
p = _pid;
end:
!flag; /* executable only if flag is false */
printf("pluto unblocked\n");
flag = !flag;
};
i++;
:: else -> break;
od;
};
中的描述准确无误。
~$ spin -search -bfs test.pml # -bfs: breadth-first-search, results in a
# shorter counter-example
pan:1: assertion violated (p==_pid) (at depth 6)
pan: wrote test.pml.trail
(Spin Version 6.4.3 -- 16 December 2014)
Warning: Search not completed
+ Breadth-First Search
+ Partial Order Reduction
Full statespace search for:
never claim - (none specified)
assertion violations +
cycle checks - (disabled by -DSAFETY)
invalid end states +
State-vector 20 byte, depth reached 6, errors: 1
15 states, stored
10 nominal states (stored-atomic)
0 states, matched
15 transitions (= stored+matched)
5 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.001 equivalent memory usage for states (stored*(State-vector + overhead))
0.290 actual memory usage for states
128.000 memory used for hash table (-w24)
128.195 total actual memory usage
pan: elapsed time 0 seconds
如果我们使用 Spin 执行形式验证,它会发现违反该属性的执行跟踪:
~$ spin -t -p -l -g test.pml
违反断言,如文档中所述。您可以按如下方式重播无效的执行跟踪:
flag:
仔细检查。现在,如果您对pippo
内的说明pippo
发表评论并重复验证过程,那么您会看到赢得了#{1}} t是违反断言的任何执行跟踪。 这是因为d_step {}
的原子序列中没有其他指令可以阻止,因此原子性永远不会丢失。
TEST 2:使用atomic
现在,使用相同的代码示例,将pippo
内的d_step
关键字替换为bool flag;
pid p;
active proctype pippo ()
{
byte i;
do
:: i < 10 ->
d_step {
true ->
p = _pid;
flag; /* executable only if flag is true */
printf("pippo unblocked\n");
flag = !flag;
assert(p == _pid);
};
i++;
:: else -> break;
od;
};
active proctype pluto ()
{
byte i;
do
:: i < 10 ->
atomic {
true ->
p = _pid;
end:
!flag; /* executable only if flag is false */
printf("pluto unblocked\n");
flag = !flag;
};
i++;
:: else -> break;
od;
};
:
~$ spin -search -bfs test.pml
pan:1: block in d_step seq (at depth 2)
pan: wrote test.pml.trail
(Spin Version 6.4.3 -- 16 December 2014)
Warning: Search not completed
+ Breadth-First Search
+ Partial Order Reduction
Full statespace search for:
never claim - (none specified)
assertion violations +
cycle checks - (disabled by -DSAFETY)
invalid end states +
State-vector 20 byte, depth reached 2, errors: 1
4 states, stored
4 nominal states (stored-atomic)
0 states, matched
4 transitions (= stored+matched)
0 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.000 equivalent memory usage for states (stored*(State-vector + overhead))
0.290 actual memory usage for states
128.000 memory used for hash table (-w24)
128.195 total actual memory usage
pan: elapsed time 0 seconds
如果您正式验证此模型,您会发现它仍然找到了一个反例,但这次出现了不同的错误:
~$ spin -t -p -l -g test.pml
using statement merging
1: proc 1 (pluto:1) test.pml:26 (state 1) [((i<10))]
2: proc 0 (pippo:1) test.pml:8 (state 1) [((i<10))]
3: proc 0 (pippo:1) test.pml:9 (state 8) [(1)]
3: proc 0 (pippo:1) test.pml:11 (state 3) [p = _pid]
spin: trail ends after 3 steps
#processes: 2
flag = 0
p = 0
3: proc 1 (pluto:1) test.pml:27 (state 7)
3: proc 0 (pippo:1)
2 processes created
对应于以下执行跟踪:
pippo
问题是d_step
序列中的d_step
阻塞,这违反了{{1}的概要中的第三个条件 } linked documentation,完全如上所述。
仔细检查。同样,如果您对flag;
说明发表评论,您会发现不会有任何错误跟踪。