本页目录
futex: 用户态锁的内核心跳
覆盖: futex(FUTEX_WAIT/FUTEX_WAKE) → pthread_mutex 内部 → PI futex → robust futex → futex2 (6.x) 适用: Linux 用户态, glibc pthread, 任何语言运行时
概述
futex (Fast Userspace muTEX) 是 Linux 上所有用户态同步原语的基础。pthread_mutex、semaphore、barrier、Rust std::sync::Mutex、Go runtime 的信号量——全部基于 futex。它的核心思想是:竞争少时在用户态解决(原子的 CAS),只在真的需要等待/唤醒时才进内核。
futex 系统调用
// futex(uaddr, futex_op, val, timeout, uaddr2, val3);
// 等待: 如果 *uaddr == val → 睡眠等待
;
// 唤醒: 唤醒最多 val 个等待在 uaddr 上的线程
;
// 等待 + 原子操作 (FUTEX_OP):
// 如果 *uaddr2 == val3 → uaddr2 += op → 然后 FUTEX_WAIT on uaddr
pthread_mutex 内部: futex 经典模式
// glibc: nptl/pthread_mutex_lock.c (简化)
// 状态: 0=空闲, 1=locked (无等待), 2=locked (有等待)
void
void
分析
无竞争: lock + unlock 全程 2 次 atomic CAS → ~20ns → 零系统调用!
轻微竞争: lock 慢路径, unlock 无等待者 → 1 futex_wake per lock cycle
重度竞争: lock 始终在等待 → 1 futex_wait + 1 futex_wake per lock cycle
这就是为什么"锁很慢"其实是"锁竞争很慢"
PI futex: 优先级继承
// 问题: 高优先级线程等锁 → 低优先级持锁者被中优先线程抢占
// → 优先级反转 (Mars Pathfinder 1997)
// PI futex: 持锁者临时提升到等待者中最高的优先级
;
// → 内核 futex(PI) 机制自动管理优先级 → 适合实时系统
Robust futex: 持锁者崩溃保护
// 问题: 线程持锁时崩溃 → 锁永远不释放 → 其他线程死锁
// Robust mutex:
;
;
// 如果返回 EOWNERDEAD:
// → 上一个持锁者崩溃 → 锁处于"脏"状态
// → 需要检查数据结构并修复 → pthread_mutex_consistent(&m)
futex2: 新一代 (6.x)
// 当前 futex 的问题:
// - 只有 32-bit futex word (需要 64-bit 时只能用额外的锁)
// - NUMA-unaware (唤醒可能在远程 NUMA 节点的 CPU)
// - 没有 deadline-aware waiting
// futex2 (6.x, discussion since 5.x):
// - 支持 8/16/32/64-bit futex word
// - NUMA-aware wake (优先唤醒本地节点等待者)
// - FUTEX_WAIT_MULTIPLE (同时等待多个 futex, 类似 select)
参考
- man: futex(2), pthread_mutex(3)
- 源码: kernel
kernel/futex/, glibcnptl/pthread_mutex_lock.c - LWN: "Futexes are tricky", "The futex2 proposal"
- 论文: "Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux" (2002)
关键词: futex, FUTEX_WAIT, FUTEX_WAKE, pthread_mutex, CAS, PI futex, robust futex, futex2