[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fiwvY3h7DBtoMOuRXE9SBX2SbbZUDnAd4pNhKeEbproA":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},"15988123-6303-4ab1-ba01-dcc41f36329f","article","Futex：Linux 的锁为什么大多数时候根本不需要进内核？","futex-fast-userspace-locking","Futex 把无竞争时的锁操作留在用户态，只有真正需要睡眠和唤醒时才进入内核，是 Linux 高性能锁的关键低层构件。","Linux 里的很多锁看起来像内核对象，实际上在没有竞争时根本不会进入内核。Futex（Fast Userspace muTEX）就是这种设计的代表：把大多数状态放在用户态原子变量里，只有线程真的需要睡眠或唤醒时，才请内核介入。\n\n可以想象一栋办公楼的门禁。平时门是开的，员工读取一个共享状态就能直接进出；只有两个人同时到门口、需要排队时，门卫才记录等待者并安排唤醒。如果每个人每次进楼都先去门卫处登记，系统就会把大量时间浪费在上下文切换上。Futex 先走用户态快速路径，避免了这份固定成本。\n\n一个典型互斥锁会用原子操作尝试把状态从未占用改成占用。成功时，整个加锁和解锁都可能只涉及用户空间的内存访问；失败时，线程调用 futex wait，把自己挂到内核等待队列，并在状态满足条件时睡眠。持锁线程释放锁后，如果发现有等待者，再调用 futex wake 唤醒其中一个或一批线程。\n\nFutex 的一个重要语义是“可能伪唤醒”，所以等待者不能只睡一次，而要放在循环里反复检查条件。这种设计也避免了丢失唤醒：调用 wait 前要把期望值交给内核，只有共享变量仍等于这个值时才睡眠。用户态的原子检查和内核态的条件等待因此衔接在一起。\n\n它并不是直接给应用提供一把完整的高级锁，而是一个低层构件。线程库用它构造互斥锁、条件变量、读写锁和信号量，并负责公平性、优先级、超时和错误处理。理解 Futex 后，就能解释为什么高性能锁在无竞争时很轻，却在竞争激烈时会突然出现调度、唤醒和上下文切换成本。\n\n锁的公平性也不是 Futex 自动提供的。多个等待线程被唤醒后，谁先重新抢到用户态状态，取决于线程调度、优先级和实现策略；高优先级任务还可能被低优先级持锁者拖住。线程库会在自旋、排队、唤醒和让渡之间寻找平衡，应用则应尽量缩短持锁区，避免把昂贵 I\u002FO 放进锁里。\n\n资料来源：[Linux futex(7) 手册](https:\u002F\u002Fman7.org\u002Flinux\u002Fman-pages\u002Fman7\u002Ffutex.7.html)","\u002Fuploads\u002F2026-09-26\u002F90e98cc8-e57b-4dea-afc7-2afe7550d483.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},"a202d639-99a6-488a-a712-4d4c6ffd7e15","开发","dev",null,"Linux futex(7) 手册","https:\u002F\u002Fman7.org\u002Flinux\u002Fman-pages\u002Fman7\u002Ffutex.7.html","published",false,45,0,"2026-09-27T00:00:00.000Z","2026-09-26T16:25:54.119Z",[45,53,61],{"id":46,"type":6,"title":47,"slug":48,"summary":49,"coverUrl":50,"authorName":14,"sno":40,"publishedAt":51,"createdAt":52},"4ce57934-2b23-41a1-800e-bb2d8ab36684","Wasm Component Model：不同语言写的模块怎样用同一套接口协作？","wasm-component-model-wit-interfaces","WebAssembly Component Model 用有类型的接口描述组件如何交换数据与调用功能，WIT 则帮助表达这些接口。本文用模块化电器说明跨语言组合的意义，也指出它不代表程序脱离运行时就能在任何环境原样运行。","\u002Fuploads\u002F2026-10-17\u002F0eb1c88d-dc1f-486d-8194-54f72dd215ec.jpg","2026-10-17T00:00:00.000Z","2026-10-17T03:08:52.474Z",{"id":54,"type":6,"title":55,"slug":56,"summary":57,"coverUrl":58,"authorName":14,"sno":40,"publishedAt":59,"createdAt":60},"07fe8e6e-82b0-46cc-9015-c6d027564430","pidfd：进程号会被重用，怎样才能稳定指向一个进程？","linux-pidfd-stable-process-reference","Linux pidfd 用文件描述符稳定引用一个进程，避免退出后的 PID 被重用而误操作新进程。本文介绍它的等待、信号用途和版本边界。","\u002Fuploads\u002F2026-10-06\u002F699e59f8-693f-47cb-87b1-c51764d1a679.jpg","2026-10-06T00:00:00.000Z","2026-10-06T07:51:27.054Z",{"id":62,"type":6,"title":63,"slug":64,"summary":65,"coverUrl":66,"authorName":14,"sno":67,"publishedAt":42,"createdAt":68},"69224a1f-e0fc-4431-a3bd-acc1d81523d0","io_uring：Linux 如何用两个环形队列批量处理异步 I\u002FO？","io-uring-async-io-rings","io_uring 通过提交队列和完成队列连接应用与内核，让大量 I\u002FO 请求可以批量提交与收取结果，减少固定交互成本。","\u002Fuploads\u002F2026-09-26\u002F0eb80204-5abc-41e2-8c8a-0e1ac633b209.jpg",46,"2026-09-26T16:25:57.069Z"]