采用反证法证明含原子操作的C++多线程程序行为是否正确?
关于C++原子操作程序行为的证明正确性疑问
示例代码
#include <thread> #include <atomic> int main(){ std::atomic<int> val = 0; std::atomic<bool> flag = false; std::jthread t1([&](){ if(val.load(std::memory_order::relaxed) == 1){ // #1 flag.store(true, std::memory_order::release); // #2 } }); std::jthread t2([&](){ while(!flag.load(std::memory_order::acquire)); // #3 val.store(1,std::memory_order::relaxed); // #4 }); }
反证法证明过程
我尝试通过反证法证明该程序的行为:
首先,假设反事实情况:#3处的循环退出。
基于该假设前提,推导如下逻辑语句:
- #3处循环退出 ⟾ #3读取自#2
[stmt.while] p1:while语句中,子语句会重复执行,直到条件([stmt.pre])的值变为false。
- #3读取自#2 ⟾ #2在程序生命周期内已执行
[intro.races] p10:原子对象M的取值(由求值B确定)是由某个修改M的未指定副作用A存储的值,且B不先于A发生。
- #2在程序生命周期内已执行 ⟾ #1处if语句的条件为true
[stmt.if] p1:若条件([stmt.pre])为true,则执行第一个子语句;若存在else部分且条件为false,则执行第二个子语句。
- #1处if语句的条件为true ⟾ #1读取自#4
应用假言三段论,可得出结论:
- #3处循环退出 ⟾ #1读取自#4
此外,#3读取自#2意味着#2 happens-before #3,进而#1 happens-before #4,这说明#1无法读取自#4。由此可推导:
- #3读取自#2 ⟾ ¬(#1读取自#4)
再次对第1条和第6条推导应用假言三段论,可得:
- #3处循环退出 ⟾ ¬(#1读取自#4)
结合第5条和第7条推导,得出矛盾:
#3处循环退出 ⟾ ¬(#1读取自#4) ∧ (#1读取自#4)
即:
#3处循环退出 ⟾ False
注:符号⟾表示逻辑蕴含。
因此,矛盾说明假设前提不成立,#3处的循环无法在该程序中退出。
疑问
请问这种方法是否属于正确的正式证明方式?
内容的提问来源于stack exchange,提问作者xmh0511
相关产品推荐
相关产品推荐

