[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f0Sqzygspy0OOiwXvMc8j3wwnyurDr_H92k1XZ2OvxrQ":3},{"item":4,"related":44},{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":35,"sourceName":36,"sourceUrl":37,"status":38,"seoTitle":7,"seoDescription":9,"canonicalUrl":35,"isFeatured":39,"sno":40,"sortOrder":41,"publishedAt":42,"updatedAt":43,"createdAt":43},"23b5596a-29ab-4ff8-8237-1fd34d8e0bd1","article","Seqlock：读者不加锁，为什么还能读到一份一致的数据？","seqlock-sequence-counter-explained","Seqlock 让读者先后读取序列号并在变化时重试，以校验快照是否被写者打断，适合读多写少且字段可安全复制的数据。","如果一个数据结构读得极多、写得很少，读者为了一次快照去抢锁，可能比真正读取字段还贵。Seqlock（序列锁）提供了另一种思路：读者先读一个序列号，再读取数据，最后再读一次序列号。如果两次序列号不同，或者序列号处在写入中的状态，读者就丢弃结果重试。\n\n它像餐厅门口的换菜牌。没有人写菜单时，牌子显示偶数；厨师开始修改时先把牌子翻成奇数，完成后再翻回新的偶数。顾客可以不排队直接看菜单，但必须在离开前再看一眼牌子。如果牌子在中途变过，说明自己可能读到了半成品，就重新查看。\n\n一个常见的读流程是：读取序列计数器，确认它不是奇数；复制需要的字段；再次读取计数器；只有前后相同才接受快照。写流程则先让计数器进入奇数状态，修改数据，最后发布偶数状态。读者不需要阻塞写者，写者也不必等待所有读者离开，因此在读多写少的结构上很高效。\n\n但 Seqlock 并不适合所有数据。读者可能反复重试，写者很忙时甚至长期得不到稳定快照；数据里如果包含指针，写者修改或释放指向对象后，读者即使最后发现序列号变化，也可能已经访问了失效地址。因此它更适合整数、时间戳、统计值等可以安全复制和校验的字段，不适合随意包裹复杂对象。\n\n理解序列锁的重点，是把“读到一致值”与“读操作从未被打断”区分开。读者允许被写者打断，但不接受不确定的结果。它把阻塞等待换成了校验和重试，也提醒我们：无锁不等于无成本，成本只是从排队转移到了版本检测、内存顺序和最坏情况下的重试次数。\n\n在实践中，读者还要把“复制字段”设计成一个足够短的临界窗口，否则写者越活跃，重试概率越高。工程上常把相关字段打包成小结构，避免跨越多个指针或可变容器。对监控快照、时间状态和硬件计数器来说，少量重试往往比互斥等待更划算；对写入持续爆发的场景，则应重新评估是否需要读写锁或版本化数据结构。\n\n资料来源：[Linux Kernel Documentation：Sequence counters and seqlocks](https:\u002F\u002Fcdn.kernel.org\u002Fdoc\u002Fhtml\u002Flatest\u002Flocking\u002Fseqlock.html)","\u002Fuploads\u002F2026-09-26\u002Fe6a9caee-7551-469f-9b16-d27fcc97f034.jpg",[],[],"Foundit","https:\u002F\u002Ffoundit.cn","foundit-ai-editorial",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31],{"id":24,"name":25,"slug":26},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":28,"name":29,"slug":30},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",{"id":32,"name":33,"slug":34},"4c2bbea6-eab7-40a8-8447-1de478ff7749","分析","analyse",null,"Linux Kernel Documentation：Sequence counters and seqlocks","https:\u002F\u002Fcdn.kernel.org\u002Fdoc\u002Fhtml\u002Flatest\u002Flocking\u002Fseqlock.html","published",false,44,0,"2026-09-27T00:00:00.000Z","2026-09-26T16:25:51.305Z",[45,53,62],{"id":46,"type":6,"title":47,"slug":48,"summary":49,"coverUrl":50,"authorName":14,"sno":51,"publishedAt":42,"createdAt":52},"5e0c84da-6011-41e8-b1f7-726c8bf0b30a","RCU：读多写少的系统，为什么敢让读者几乎不加锁？","rcu-read-copy-update-explained","RCU 把共享数据的更新与旧版本回收拆开，让读者以极低成本读取，同时等待所有旧读者离开后再释放内存。本文用导览图解释它的读侧、宽限期与适用边界。","\u002Fuploads\u002F2026-09-26\u002F3398ce37-ca4f-4cc3-84b3-fe931d2f055d.jpg",41,"2026-09-26T16:25:40.784Z",{"id":54,"type":6,"title":55,"slug":56,"summary":57,"coverUrl":58,"authorName":14,"sno":59,"publishedAt":60,"createdAt":61},"0bc79f1c-f305-4d64-a9f8-589d1d6da0b3","EEVDF：Linux 如何判断哪个任务“最该先用 CPU”？","eevdf-linux-fair-cpu-scheduling","EEVDF 是 Linux 调度器的一种公平调度思路：先判断任务是否获得了应有份额，再按虚拟截止时间安排运行机会。本文用共享厨房的比喻，解释它如何兼顾长期公平与短期响应，并澄清它并非硬实时保证。","\u002Fuploads\u002F2026-10-13\u002Fdc59d374-8c78-41ba-bdfe-a6f0e62ab246.jpg",43,"2026-10-13T00:00:00.000Z","2026-10-13T02:13:28.103Z",{"id":63,"type":6,"title":64,"slug":65,"summary":66,"coverUrl":67,"authorName":14,"sno":68,"publishedAt":42,"createdAt":69},"6ced249d-9a51-438b-b51a-8ebb9a27a949","NUMA：同一台机器上的内存，为什么有的更近更快？","numa-non-uniform-memory-access","NUMA 把多路服务器的 CPU 与内存看成多个距离不同的节点，本地访问通常更快，线程与数据的放置会直接影响吞吐和尾延迟。","\u002Fuploads\u002F2026-09-26\u002F1bf98759-c58b-4537-a274-ebc889f06f89.jpg",48,"2026-09-26T16:26:03.813Z"]