结论:futex(fast userspace mutex)是 Linux 的底层同步原语:锁状态是用户态的一个整数,无竞争时完全在用户态用原子操作完成加解锁,不发生系统调用;只有在真正竞争(锁已被持有)时才陷入内核,通过 futex 系统调用睡眠等待或被唤醒。pthread mutex、glibc 条件变量、Go 的 sync.Mutex 都建立在它之上。
展开:状态机通常三态:0 未锁、1 已锁无等待者、2 已锁有等待者。加锁:CAS 0→1 成功即得锁(纯用户态,一条指令);失败则置 2 并 futex(FUTEX_WAIT) 挂起。解锁:原子减到 0,若原值是 2 则 futex(FUTEX_WAKE) 唤醒等待者。关键语义:内核按 futex 字的地址维护等待队列,WAIT 时先校验用户态值仍等于预期(防止"检查后到睡眠前锁被释放"的丢失唤醒),不等则直接返回 EAGAIN。性能意义:无竞争路径与自旋锁成本相当,竞争时才付出系统调用,兼顾了两类负载。易错点:futex 是"地址即队列",跨进程共享需映射同一块内存;futex 字必须 4 字节对齐;程序退出时内核靠 robust futex 机制恢复持锁死亡的锁,避免其他进程永久阻塞。
// 加锁核心:无竞争不进内核
int expected = 0;
if (atomic_compare_exchange(&lock, &expected, 1))
return; // 拿到锁
futex(&lock, FUTEX_WAIT, 2, ...); // 有竞争才进内核
追问方向:PI futex(FUTEX_LOCK_PI)如何解决优先级反转、Go 运行时为什么不直接用 pthread mutex。