RCU 与读多写少同步

这页讲的是:有些内核数据结构会被大量读取、偶尔修改,如果每次读都重锁,代价会很高。学这页的重点,是理解 RCU 不是“另一种锁”的语法替代,而是一套围绕读路径尽量轻、更新延后回收的同步思路。

这块是什么

RCU 与读多写少同步,讲的是当很多 CPU 或执行路径都想频繁读取某份共享数据,而写操作相对少时,Linux 怎样用“读者尽量不停下来、更新者分阶段替换、旧对象延后回收”的办法,把并发成本降下来。它常出现在线路长、读多写少、对吞吐敏感的数据路径里。

可以把它理解成:图书馆要更新楼层导览图,不是先把旧图全撤掉再让所有人等着,而是先挂上新版,再等确定所有正在看旧图的人都走开后,才把旧图收走。

它负责什么

让读路径更轻

  • 让大量读取共享数据的路径少受重锁影响
  • 减少频繁读场景下的同步开销
  • 让多核并发读取更容易扩展
  • 把成本尽量从读侧挪到更新和回收阶段

分离更新与回收

  • 更新时先替换到新版本或新指针
  • 旧对象不立刻销毁
  • 等确认读者都离开旧视图后再回收
  • 降低读者踩到失效对象的风险

支撑高并发共享数据

  • 适合读多写少的数据结构
  • 常与链表、查找结构、路由与对象发布场景一起出现
  • 让“很多人看、少数人改”不必总靠粗锁硬顶
  • 把同步设计和生命周期设计绑到一起考虑

为什么它不是“再学一种锁”

如果想得太简单会怎样真正关键在哪
把 RCU 当成普通互斥锁会忽略它并不主要靠阻止读者进入来保证正确性。它更像是在管理“读者看见什么、旧对象何时才能死”。
只盯着更新动作容易低估延后回收和宽限期的重要性。很多正确性其实落在“旧对象不能死太早”上。
以为它适合所有共享数据会把写频繁、修改复杂的场景也硬套进去。RCU 更擅长读多写少,而不是通吃所有并发问题。
以为它解决了全部同步问题可能忽略状态一致性、写写竞争和复合更新仍需别的约束。RCU 主要照顾读者存活与可见性,不替代所有并发控制。

关键概念

概念现在怎么理解
RCU一种偏向读多写少场景的同步思路,让读者轻量读取,更新与回收分阶段完成。
读侧临界区读者在这段期间看到的对象必须继续有效,不能被过早回收。
宽限期等待所有旧读者离开旧视图的那段过渡时间。
发布与替换更新者先把新对象或新版本挂出来,再逐步撤掉旧对象。
延后回收不是没人引用就立刻 free,而是等安全时机到了再回收。

为什么重要

常见误解

它不负责什么

和其他模块的关系

相关模块关系
并发控制RCU 是并发控制里最容易让人感觉“不是传统锁”的一类关键思路。
kref 与引用计数两者都关心对象何时还能活着,但一个偏共享读视图,一个偏显式持有关系。
等待队列 / workqueue延后回收和异步清理常会在这些后台路径里真正发生。
网络 / 路由 / 对象发布很多读多写少的数据路径会用类似思路组织对象可见性。

读完这页后,你应该能回答

后面适合继续问:RCU 和引用计数最容易混在哪?为什么很多人会把“发布新对象”和“回收旧对象”误当成一步?读侧轻量的代价到底被挪到了哪里?