“Push-button” Verification 🎖

我们 (在完全不理解算法的前提下) 证明了 Sequential 内存模型下 Peterson's Protocol 的 Safety。它能够实现互斥。

并发编程比大家想象得困难

自动遍历状态空间的乐趣

可以帮助我们快速回答更多问题

  • 如果结束后把门上的字条撕掉,算法还正确吗?
    • 在放下旗子之前撕
    • 在放下旗子之后撕
  • 如果先贴标签再举旗,算法还正确吗?
  • 我们有两个 “查看” 的操作
    • 看对方的旗有没有举起来
    • 看门上的贴纸是不是自己
    • 这两个操作的顺序影响算法的正确性吗?
  • 是否存在 “两个人谁都无法进入临界区” (liveness)、“对某一方不公平” (fairness) 等行为?
    • 都转换成图 (状态空间) 上的遍历问题了!

Model Checker 和自动化

电脑为什么叫 “电脑”

  • 就是因为它能替代部分人类的思维活动

回忆:每个班上都有一个笔记和草稿纸都工工整整的 Ta

  • 老师:布置作业画状态图
    • Ta:认认真真默默画完
      • 工整的笔记可以启发思维
      • 但 scale out 非常困难
    • 我:烦死了!劳资不干了!玩游戏去了!
      • 计算思维:写个程序 (model checker) 来辅助
        • 任何机械的思维活动都可以用计算机替代
        • AI 还可以替代启发式/经验式的决策

从模型回到现实……

回到我们的假设 (体现在模型)

  • Atomic load & store
    • 读/写单个全局变量是 “原子不可分割” 的
    • 但这个假设在现代多处理器上并不成立
  • 所以实际上按照模型直接写 Peterson 算法应该是错的

“实现正确的 Peterson 算法” 是合理需求,它一定能实现

  • Compiler barrier/volatile 保证不被优化的前提下
    • 处理器提供特殊指令保证可见性
    • 编译器提供 __sync_synchronize() 函数
      • x86: mfence; ARM: dmb ish; RISC-V: fence rw, rw
      • 同时含有一个 compiler barrier

🌶️ 维持实现到模型的对应

Peterson 算法:C 代码实现演示

  • 一些有趣的问题
    • Compiler barrier 能够用吗?
    • 哪些地方的 barrier 是不可少的?
  • 测试只能证明 “有问题”,不能证明 “没问题”

编译器到底做了什么?

  • 推荐:godbolt.org,你不用装那些 cross compiler 了
    • 你甚至可以看到 compiler barrier 是如何在优化中传递的
      • 再一次:自动化 & 可视化的意义
    • 不懂可以把代码直接扔给 ChatGPT