Go Runtime(九):Runtime信号量与同步原语

本文源码基线为 Go 1.26.2、Linux/amd64。sync 的公开语义由标准库保证;本文讨论的状态位、队列和 runtime 接口属于版本相关实现,不应被业务代码依赖。 sync.Mutex 的竞争慢路径、RWMutex 的读写协调和 WaitGroup 的等待,最终都需要把 G 停下来并在条件满足时重新放回调度器。它们共享 runtime semaphore,但并不共享完全相同的高层状态机。 先建立边界:runtime semaphore 是“按地址等待与唤醒”的底层设施,不是公开的计数信号量类型。存放在 uint32 地址中的 token 只服务于防丢唤醒和交接协议。 先锁定公开契约 Mutex.Unlock 与之后的 Lock、Once 中 f 的完成与所有 Do 返回、WaitGroup.Done 与它解除的 Wait 都建立文档规定的 happens-before 关系。正确性应依赖这些公开保证,而不是当前源码中的 CAS 顺序、starvation 阈值或 treap 形状。 同理,TryLock 失败不建立同步关系,RWMutex 不支持升级/降级,复制首次使用后的同步对象属于错误用法。源码分析应解释契约如何实现,而不是把私有机制升级为新契约。 一次竞争如何穿过各层 TEXT高层状态机 Mutex/RWMutex/WaitGroup/Cond/Once | 原子快路径与竞争判定 | runtime sema / notifyList | sudog + goparkunlock / goready | GMP scheduler 原子操作避免无竞争路径进入内核或调度器;runtime 队列解决竞争时的睡眠与唤醒;调度器决定被 ready 的 G 何时真正运行。Linux futex 不是这些普通路径的直接一一对应物:runtime 自己调度 G,只有 OS 线程级 runtime 锁和休眠等更底层场景才需要平台同步原语。 ...

August 18, 2026