seqcount / seqlock 与顺序计数同步
这页讲的是:有些共享数据读得非常频繁,大家不想让所有读者都老老实实排队,但又必须知道自己有没有读到写入中的不完整快照。学这页的重点,是理解 seqcount / seqlock 的思路不是“绝不重读”,而是“让读者先快读,若撞上写者就认错重来”。
这块是什么
seqcount / seqlock 与顺序计数同步,讲的是 Linux 怎样在一些读非常频繁、写相对较少的共享数据场景下,让读者先不和彼此互斥,而是通过顺序计数判断“这次读到的是不是稳定版本”。它关注的是“读者快速尝试,若不稳定就重试”,而不是让所有读者都无条件排队等待。
可以把它理解成:你在抄一块公告板内容,如果管理员正在改板子,你可能会抄到一半发现前后对不上。这时不是强迫所有人排队,而是让你确认版本不一致就重抄一遍。
它负责什么
让读者先快速读取
- 如果每个读者都去抢重锁,读路径代价可能太高
- 顺序计数允许读者先快速拿一份快照
- 把常见的“无人写入”情况走得更轻
- 让读多场景少一点排队感
在写入干扰时要求重试
- 写者修改期间,读者可能拿到不一致片段
- 顺序计数帮助读者识别这次读是否可靠
- 如果撞上写入,就放弃本次结果重来
- 让“快读”不以错误快照为代价
把读写不对称进一步压榨出来
- 有些场景甚至不想让读者拿共享锁
- 只要读者愿意偶尔重试,就能换来更轻的读路径
- 让无写入时的读取非常顺滑
- 把少量重试成本换成高频读扩展性
为什么它不是“万能无锁读取”
| 如果想得太简单 | 会怎样 | 真正关键在哪 |
|---|
| 觉得读者既然不排队就一定最好 | 会忽略一旦写入变多,重试成本可能明显上升。 | 它最适合写少且每次重读代价可接受的场景。 |
| 把它当完全无条件一致快照 | 会漏掉读者其实承担了“发现不稳就重来”的责任。 | 正确性依赖重试协议,而不是一次读必然成功。 |
| 觉得它能替代所有读写锁 | 会忽略并不是所有对象都适合反复重读或容忍中途失败。 | 对象形态和读写模式必须匹配这种设计。 |
| 不把顺序和可见性当回事 | 会让读者误把半更新状态当完整结果。 | 这类机制本质上强依赖正确的顺序语义。 |
关键概念
| 概念 | 现在怎么理解 |
|---|
| seqcount | 用顺序计数告诉读者:这次读前后的版本号是否稳定一致。 |
| seqlock | 在顺序计数思想上,再明确写者更新时的独占修改路径。 |
| 重试 | 读者发现自己撞上写入,就放弃本次结果重新读。 |
| 稳定快照 | 读者前后看到的版本一致,说明读到的是同一轮稳定状态。 |
| 写少读多 | 这类同步最适合大量读取、少量更新的对象形态。 |
为什么重要
- 它解释了为什么读优化不只有“给读者共享锁”这一种路,还有“让读者必要时认错重来”的思路。
- 很多时间、统计或系统状态快照类对象,都更适合这种轻量读路径。
- 理解这层后,你会更容易把 rwsem、RCU、内存屏障和读写模式选择放在一张图里看。
- 它让你看到:有时系统不是强迫每次都一次成功,而是用低成本失败重试换来高频路径更轻。
常见误解
- 误解一:seqlock 就是比 rwsem 更先进。实际上它们适合的对象和读者责任完全不同。
- 误解二:读者不加锁就一定没有代价。实际上重试本身就是代价,只是平时不显眼。
- 误解三:只要会重试,就什么对象都能这样做。实际上有些对象太大、太复杂或读副作用太重,不适合反复重读。
它不负责什么
- 它不适合写入频繁、读一次成本很高或不能轻易重试的场景。
- 它不替代对象生命周期管理,读到的对象是否仍可安全使用仍要配合别的规则。
- 它不自动消除顺序问题,很多正确性仍依赖屏障和写者协议配合。
和其他模块的关系
| 相关模块 | 关系 |
|---|
| rwsem | 都偏向读多写少,但 rwsem 让读者正式持锁,seqcount / seqlock 更强调读者快速尝试加重试。 |
| memory barriers | 读者能不能正确判断一轮写入是否完整,离不开正确的顺序和可见性保证。 |
| RCU | 两者都在减轻读路径负担,但一个靠重试快照,一个更偏向延后回收和轻读访问。 |
| 时间与状态快照 | 很多只想快速读取当前状态、又能接受偶尔重试的场景都容易考虑这类机制。 |
读完这页后,你应该能回答
- 为什么 seqcount / seqlock 的核心不是“读者从不失败”,而是“失败时能识别并重试”?
- 为什么这类机制特别适合写少读多、且读者能接受偶尔重读的对象?
- 为什么它和 rwsem、RCU 看起来都在优化读路径,但读者承担的责任其实不一样?
后面适合继续问:什么时候快照类数据更适合 seqcount,而不是 rwsem?读者重试在高写入压力下会出现什么体感问题?seqlock 和 RCU 最容易被混在哪一层?