[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fXqvrgU2Un1hDmenS-rLVtmcU4ovTHHeBnyaD4BKGza4":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},"3ee91529-a5cf-40b1-ab91-69df08e489ea","article","Hazard Pointers：无锁数据结构删除节点后，谁来保证它还没被读到？","hazard-pointers-memory-reclamation","Hazard Pointers 让线程在访问节点前公开保护标记，删除者延迟回收并扫描这些标记，从而避免悬空指针与部分 ABA 风险。","无锁数据结构最容易被忽略的一幕，发生在“删除”之后。一个线程把链表节点从结构中摘下来，并不意味着另一个线程不会马上解引用它。如果节点被立刻释放，后来的读取就可能变成悬空指针。Hazard Pointers（危险指针）是一套让无锁回收变得可验证的办法。\n\n它的做法很像图书馆的“正在阅读”登记。线程准备访问一个可能被删除的节点时，先把节点地址写入自己的危险指针槽位，再重新确认节点仍然在链表中。如果节点在这两步之间被别人摘走，线程发现校验失败，就放弃本轮访问并重试；如果节点仍然存在，它才放心读取。删除者不会立即释放摘下来的节点，而是把它放进退休列表，之后扫描所有线程公开的危险指针。\n\n只有当一个退休节点没有出现在任何危险指针里，回收者才可以真正释放它。这个过程还要处理一个叫 ABA 的问题：地址 A 曾经被删除，内存又被重新分配给另一个对象，某个线程只比较地址时会误以为“什么都没变”。危险指针通过要求读者先公开保护、删除者延迟回收，降低了地址被过早复用造成误判的风险。\n\n它的优势是边界清晰，适合栈、队列、哈希表等需要无锁读取和删除的结构，而且不要求所有线程同时停下来。代价是每个参与者都要维护保护槽位，删除者需要扫描这些槽位，退休对象也可能在很长时间内占用内存。代码还必须严格遵守“发布保护—重新验证—访问对象”的顺序，少一步都可能留下竞态。\n\n所以，危险指针不是一种更快的垃圾回收器，而是一种显式的生命周期协议：我即将访问这个节点，请暂时不要回收它；等我清除保护后，系统才有资格判断它是否安全。理解这个协议，才能看懂很多看似没有锁、实际依靠精细内存管理维持安全的并发库。\n\n资料来源：[Hazard Pointers：Safe Memory Reclamation for Lock-Free Objects](https:\u002F\u002Fwww.cs.otago.ac.nz\u002Fcosc440\u002Freadings\u002Fhazard-pointers.pdf)","\u002Fuploads\u002F2026-09-26\u002Ffd52a815-7e19-4622-9182-6ca2df8e8144.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},"68cedb55-2cac-412f-8f81-fda8c7d686dd","思考","thought",null,"Hazard Pointers：Safe Memory Reclamation for Lock-Free Objects","https:\u002F\u002Fwww.cs.otago.ac.nz\u002Fcosc440\u002Freadings\u002Fhazard-pointers.pdf","published",false,42,0,"2026-09-27T00:00:00.000Z","2026-09-26T16:25:44.416Z",[45,53,62],{"id":46,"type":6,"title":47,"slug":48,"summary":49,"coverUrl":50,"authorName":14,"sno":51,"publishedAt":42,"createdAt":52},"bd1746b8-937b-48cf-ae66-0116d7062e67","Epoch Reclamation：并发程序为什么要等“这一代线程”都走完再释放内存？","epoch-based-memory-reclamation","基于纪元的回收把退休对象标记到某一代，等所有可能看见它的参与者跨过该纪元后再批量释放，适合高并发无锁结构。","\u002Fuploads\u002F2026-09-26\u002F2eb6fe27-ea9d-440a-877f-965f5158edb4.jpg",43,"2026-09-26T16:25:47.831Z",{"id":54,"type":6,"title":55,"slug":56,"summary":57,"coverUrl":58,"authorName":14,"sno":59,"publishedAt":60,"createdAt":61},"05351c3a-3592-4ecb-aaeb-276a3bb2a79e","Abstract Interpretation：静态分析为什么不用真正运行程序？","abstract-interpretation-static-analysis-explained","Abstract Interpretation 用可计算的抽象状态近似程序行为，让工具在没有真实输入的情况下发现潜在问题。本文解释抽象、保守估计、循环收敛和误报，帮助读者理解静态分析为什么既强大又不总能给出确定答案。","\u002Fuploads\u002F2026-09-20\u002F3e0cf61b-b0dc-4028-b368-c4c013d026eb.jpg",41,"2026-09-20T00:00:00.000Z","2026-09-20T03:57:49.227Z",{"id":63,"type":6,"title":64,"slug":65,"summary":66,"coverUrl":67,"authorName":14,"sno":68,"publishedAt":69,"createdAt":70},"7418caa8-c69e-4dd7-bf51-795caea4a39d","Vibe Coding 时，为什么最容易泄露 API Key 和密码","vibe-coding-api-key-secret-leak","AI 编程最容易把秘密藏进前端、日志、配置和聊天上下文。本文解释浏览器端密钥、环境变量、日志暴露和 Agent 权限的风险，并给出适合个人项目的最小安全检查清单。","\u002Fuploads\u002F2026-09-13\u002F794d5f6a-d25b-4e2c-a002-cd743a31acff.jpg",47,"2026-09-13T00:00:00.000Z","2026-09-13T11:55:51.460Z"]