原子性和顺序违反

原子性和顺序违反

2025 南京大学《操作系统原理》
原子性和顺序违反

并发编程的本质困难

人类是 sequential creature

  • 我们只能用 sequential 的方式来理解并发
    • 程序分成若干 “块”,每一块看起来都没被打断 (原子)
      • 例子:produce \to (happens-before) \to consume

并发控制的机制完全是 “后果自负” 的

  • 互斥锁 (lock/unlock) 实现原子性
    • 忘记上锁——原子性违反 (Atomicity Violation, AV)
  • 条件变量/信号量 (wait/signal) 实现先后顺序同步
    • 忘记同步——顺序违反 (Order Violation, OV)
  • Threads cannot be implemented as a library
2025 南京大学《操作系统原理》
原子性和顺序违反

那么,程序员到底用得对不对呢?

“Empirical study” 实证研究

  • 收集了 105 个真实系统的并发 bugs
    • MySQL (14/9), Apache (13/4), Mozilla (41/16), OpenOffice (6/2)
    • 观察是否存在有意义的结论

97% 的非死锁并发 bug 都是原子性或顺序错误

2025 南京大学《操作系统原理》
原子性和顺序违反

原子性违反 (Atomicity Violation)

“ABA”: 代码被别人 “强势插入”

  • 即便分别上锁 (消除数据竞争),依然是 AV
    • Diablo I 里复制物品的例子
    • Therac-25 中 “移动 Mirror + 设置状态”

center

2025 南京大学《操作系统原理》
原子性和顺序违反

原子性违反 (cont'd)

操作系统的状态也是共享状态

center

2025 南京大学《操作系统原理》
原子性和顺序违反

顺序违反 (Order Violation)

“BA”: 事件未按预定的顺序发生

  • 例子:concurrent use-after-free

center

2025 南京大学《操作系统原理》
原子性和顺序违反

动态程序分析

加强版的 LockDep

  • “打印” 程序运行时的日志
    • (实际上也许直接分析事件日志,不需要打印)
    • Memory Access, Acquire-Release, ...
      • 然后判断有没有问题
      • Lockset: 不允许访问内存时持有 “不相交” 的锁
      • Happens-before: 要求 ABA \to BBAB \to A
  • 我们也可以用 heuristics (或者 LLM) 来 “阅读” 日志是否正确
2025 南京大学《操作系统原理》
原子性和顺序违反

并发:真实世界的魔鬼 🌶️

GhostRace (USENIX Sec'24)

  • 正确的互斥、正确的同步 usefree\text{use} \to \text{free}
void T_A() {
    lock(&obj->lock);
    free(obj->something);
    obj->something = NULL;
    unlock(&obj->lock);

}
void T_B() {
    lock(&obj->lock);
    if (obj->something) {
        // changes cache on speculative execution
    }
    unlock(&obj->lock);
}
2025 南京大学《操作系统原理》