[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fqt850P4XZ7SwAuXIqyUUHug_vOfcQ1iflBi1zc3WuuQ":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},"30592878-4e41-4b1e-99c5-09c64e246942","article","False Sharing：不同线程改不同变量，为什么也会互相拖慢？","false-sharing-cache-line-contention","False Sharing 不是线程争用同一个变量，而是不同核心频繁修改同一缓存行中的独立数据。本文解释缓存一致性为什么会制造额外流量，以及如何先诊断再优化。","想象一张很长的共享办公桌：两位同事各自只动自己的文件，却因为文件恰好挤在同一个抽屉里，每次改动都让另一人的工作区失效。多线程程序里也有类似现象，名字叫 False Sharing，通常译作“伪共享”。它不是线程真的读写同一个变量，而是不同核心修改的变量落在同一条缓存行里。\n\n现代处理器不会为每个字节单独管理缓存一致性，而是以一块固定大小的数据为单位搬运和协调缓存，这块单位叫缓存行。核心 A 修改其中一个字段时，硬件一致性协议可能需要让其他核心上的对应缓存行失效。即便核心 B 改的是同一行里的另一个、逻辑上完全独立的字段，它持有的副本也可能被作废；下一次访问就得重新取得缓存行。若两个核心反复写各自的计数器，缓存行便像乒乓球一样在核心之间来回争抢。\n\n因此，程序表面上“没有共享变量”，仍可能在硬件层面共享缓存行。典型诱因是紧凑排列的计数器数组、相邻对象中的高频写字段，以及多个工作线程更新彼此相邻的统计值。读取少、写入频繁、线程又分布在不同核心时，这种一致性流量尤其值得排查。它会让并行程序扩展到更多核心后收益变小，甚至比少开几个线程还慢。\n\n排查时不要凭“看起来相邻”就立刻改结构。先用基准测试确认热点，再借助 Linux 的 `perf c2c` 等工具观察缓存行竞争，结合结构布局工具检查哪些字段同处一行。诊断证据比猜测重要，因为真正的热点也可能是锁竞争、内存带宽或调度开销。修复之后要重新测量，并关注整个工作负载，而不是只看单个微基准。\n\n常见缓解方法是让不同线程频繁写入的数据彼此隔开，例如每线程本地计数、分批汇总、调整结构布局，必要时按缓存行对齐或填充。代价是内存占用上升，数据布局更复杂，也可能损伤缓存局部性。若数据更新很少，或者这些字段总由同一个核心处理，填充反而只是在浪费内存。优化的核心不是“把所有东西都隔开”，而是先定位哪些写入确实造成跨核心争用。\n\n这个术语提醒我们：并发冲突不只发生在编程语言能看见的变量和锁上，硬件管理缓存的粒度也会影响性能。它常见于高性能服务、数据库、游戏引擎和科学计算代码，也说明“逻辑独立”不等于“物理上互不干扰”。\n\n来源：[Linux 内核文档：False Sharing](https:\u002F\u002Fdocs.kernel.org\u002Fkernel-hacking\u002Ffalse-sharing.html)","\u002Fuploads\u002F2026-10-06\u002Fc19dbbfb-ee3b-4583-8541-b8983bd30330.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：False Sharing","https:\u002F\u002Fdocs.kernel.org\u002Fkernel-hacking\u002Ffalse-sharing.html","published",false,57,0,"2026-10-06T00:00:00.000Z","2026-10-06T07:51:15.063Z",[45,54,63],{"id":46,"type":6,"title":47,"slug":48,"summary":49,"coverUrl":50,"authorName":14,"sno":51,"publishedAt":52,"createdAt":53},"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-27T00:00:00.000Z","2026-09-26T16:25:40.784Z",{"id":55,"type":6,"title":56,"slug":57,"summary":58,"coverUrl":59,"authorName":14,"sno":60,"publishedAt":61,"createdAt":62},"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":64,"type":6,"title":65,"slug":66,"summary":67,"coverUrl":68,"authorName":14,"sno":69,"publishedAt":52,"createdAt":70},"23b5596a-29ab-4ff8-8237-1fd34d8e0bd1","Seqlock：读者不加锁，为什么还能读到一份一致的数据？","seqlock-sequence-counter-explained","Seqlock 让读者先后读取序列号并在变化时重试，以校验快照是否被写者打断，适合读多写少且字段可安全复制的数据。","\u002Fuploads\u002F2026-09-26\u002Fe6a9caee-7551-469f-9b16-d27fcc97f034.jpg",44,"2026-09-26T16:25:51.305Z"]