Skip to the content.

locking.txt 中文译解

源文件:tools/memory-model/Documentation/locking.txt

文档定位

这篇文档专门讨论一个常见陷阱:共享变量通常受某把锁保护,但你又想在某些路径上不持锁地访问它们。原文的核心观点是:锁本身能提供很多排序,但一旦脱离锁语境,常常还需要额外同步。

逐节译解

Locking

最重要的一句话是:持有某把锁的 CPU,能够看到任何 CPU 在上一次释放同一把锁之前已经看到或已经做出的变化。这比“看到临界区内部的写”更强,因为它还把锁前后的可见性链起来了。

Locking and Prior Accesses

如果 CPU0 在加锁前写了 x,在锁内写了 y,CPU1 在锁内读到 y=1,那么 CPU1 在锁外随后读 x 时也必须能读到 1。也就是说,锁不只保护锁内访问,还把某些锁前访问带进了可见性链。

Locking and Subsequent Accesses

反过来也成立。如果 CPU0 在锁内读 x 时仍然看到旧值,那么它在加锁前读到的某些相关状态也必须仍是旧值。锁不仅能“带入过去”,也能“排除未来”。

Double-Checked Locking

双重检查锁定不是只加一把锁就自然正确。问题有两个:

修法是用 smp_load_acquire()smp_store_release() 给外层无锁路径补同步边。

Ordering Provided by a Lock to CPUs Not Holding That Lock

锁建立的顺序不一定会自动扩展给从未持有该锁的第三个 CPU。也就是说,锁序本身不是无条件全局广播。如果要把锁中的顺序延伸给锁外观察者,可能需要 smp_mb__after_spinlock() 之类的补强。

No Roach-Motel Locking!

所谓 “roach motel locking” 指把原本在临界区外的访问偷偷拉进临界区,以为这样只会更强。文档强调这种变换在一般情况下不成立,尤其是当锁前有自旋等待或观察逻辑时。原因是:把访问搬进临界区会改变哪些执行结果允许出现。

这篇文档的工程含义

锁是强同步原语,但“受锁保护的数据可以随便无锁看一眼”是错误直觉。只要离开锁,就重新回到 LKMM 需要显式论证的世界。

locking.txt 内容总结

源文件:tools/memory-model/Documentation/locking.txt

核心结论

锁能提供很强的排序,但这种排序主要服务于“也参与这把锁”的 CPU。对不持锁的访问者,很多你以为自然成立的结论并不成立。

关键场景

阅读建议

如果你在写“快路径无锁读,慢路径持锁改”的代码,这篇必须读。

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。