Linearizability checker: Wing-Gong-Lowe search over concurrent histories with minimal counterexample witnesses.
线程 A: x = 1 [ 0 ── 10 ]
线程 B: x = 2 [ 5 ── 15 ]
线程 A: print(x) [ 20 ── 30 ]存在一个全序,使得每个操作在它"开始到结束之间"的某一点原子生效,且该全序下的结果符合对象的顺序语义。
moon check
moon test
# 检查一份历史
moon run cmd/lincheck -- check --history examples/register_ok.jsonl --model register
# 看时间轴
moon run cmd/lincheck -- visualize --history examples/register_bad.jsonl
# 自检:生成的合法历史必须全部通过
moon run cmd/lincheck -- selfcheck --model register --seeds 100lincheck check --history <file.jsonl> --model register|counter|set|queue [--budget-ms N] [--json]
lincheck minimize --history <file.jsonl> --model register
lincheck visualize --history <file.jsonl>
lincheck gen --model register --processes 3 --ops 10 --seed 42 --consistent
lincheck selfcheck --model register --seeds 100为什么 1 和 4 要分开:1 的意思是「历史确实非线性一致」,这是一个 有效结论;4 的意思是「历史文件读不到或格式不对」,是无法判断。 混用会让脚本把「数据有问题」误当成「发现 bug」。
注意:visualize、minimize 也会按检查结果返回退出码。对 examples/register_bad.jsonl 这类故意构造的违规历史,它们返回 1 是 正确行为,不是程序出错——1 的意思就是「这份历史确实非线性一致」。 只有 check 的退出码应该被当作判断依据;visualize/minimize 返回 1 只是把它检查到的事实如实传递出来。
退出码 1 内部还有一层区分:真并发竞态 ("reason":"concurrency-race")vs 历史数据自相矛盾 ("reason":"data-inconsistency")。后者是「见证只有一条操作,且它相对 初始状态就不可能成立」,例如初值 0 的寄存器上记录了 Cas(1->2) -> true——没有并发交错能解释它,该去查历史/初值,而不是查 数据结构的竞态。人类可读解释里会直接写明「不是并发竞态」,细节见 docs/exit-codes.md。
{"id":0,"process":0,"kind":{"tag":"Write","value":1},"result":{"tag":"Ok"},"start":0,"end":10}已线性化 = {}
当前状态 = 初始状态
每步:
候选 = 所有满足条件的未完成操作:
它的 start ≤ 所有"尚未线性化"操作的最小 end
对每个候选(按 start 排序保证确定性):
若 apply(当前状态, op) 的期望返回值 == op.result:
递归(下一状态, 已线性化 ∪ {op})
否则剪枝✗ NON-LINEARIZABLE
最小化:3 → 3 个操作
再验证:仍违规 ✓
· 操作 0: proc 0 W=1 -> Ok [0..10]
· 操作 1: proc 1 W=2 -> Ok [12..20]
· 操作 2: proc 0 R -> Value(1) [30..40]
delta debugging:3 个操作中保留 3 个仍可复现违规。
· proc 0 W=1 -> Ok [0..10]
· proc 1 W=2 -> Ok [12..20]
· proc 0 R -> Value(1) [30..40]
在最少保留这么多个操作的约束下无法继续缩减:存在删掉某一条后仍违规的方向,但继续缩减会跌破最小见证下界或破坏可解释性。$ moon run cmd/lincheck -- minimize --history examples/noisy_bad.jsonl --model register
最小化:8 → 2 个操作
· 操作 2: proc 2 W=2 -> Ok [12..20]
· 操作 3: proc 3 R -> Value(0) [22..24]src/
history.mbt Operation / History / 并发判定 / JSONL
model.mbt Model trait / State / 内建模型
checker.mbt WGL 搜索 + 状态缓存
minimize.mbt delta debugging 最小化
generate.mbt 历史生成与故障注入
visualize.mbt 文本时间轴
cmd/lincheck/
main.mbt CLIInstall
Download zipLinearizability checker: Wing-Gong-Lowe search over concurrent histories with minimal counterexample witnesses.