RCU:读多写少的系统,为什么敢让读者几乎不加锁?
TL;DR
RCU 把共享数据的更新与旧版本回收拆开,让读者以极低成本读取,同时等待所有旧读者离开后再释放内存。本文用导览图解释它的读侧、宽限期与适用边界。
RCU 把共享数据的更新与旧版本回收拆开,让读者以极低成本读取,同时等待所有旧读者离开后再释放内存。本文用导览图解释它的读侧、宽限期与适用边界。

很多高并发系统有一个共同烦恼:读操作远多于写操作,但如果每次读都先抢一把锁,CPU 就会把时间花在排队上。RCU(Read-Copy Update,读-复制-更新)就是为这种场景设计的一种并发思想。它的核心不是让读者更快地抢到锁,而是让读者尽量不需要锁。
可以把一份共享配置想象成商场里的导览图。绝大多数人只是查路线,只有偶尔才有人更新地图。传统做法是在更新时把门关上,所有查询者等更新完成;RCU 则会先复制一份新地图,在新地图准备好后,把入口指针从旧地图瞬间切到新地图。已经拿到旧地图的人继续读完,后来的人直接看新地图。
这里最关键的是“更新”和“回收”被拆开了。更新者可以创建新版本、修改新版本,再发布新指针;但旧版本不能马上释放,因为某个读者可能还握着它。系统需要等到所有在更新前开始的读者都离开临界区,确认没有人再访问旧对象后,才回收旧内存。这个等待阶段常被称为宽限期(grace period)。
RCU 的读侧因此非常轻:通常只需要进入和退出一个读侧标记区,不需要原子地修改一个互斥锁状态。它特别适合内核路由表、文件系统元数据、进程信息等“读多写少”的结构。代价也很明确:更新者要承担复制和延迟回收的成本,读者不能无限期停留,否则旧版本会一直占着内存;如果数据需要频繁写入,复制成本也可能超过锁竞争成本。
工程上还要注意,RCU 保护的是“对象何时可以被释放”,并不自动保证业务字段的组合更新是一致的。发布新指针、修改对象内部字段、管理嵌套对象,都需要额外的内存顺序和生命周期设计。理解这一点后,RCU 就不再是一个神秘的内核缩写:它是在读路径上尽量少做事,把复杂度转移给版本发布、读者追踪和安全回收。



