Mutex 家族
parking_lot 的三种互斥锁共用一个原始锁:RawMutex,一个 AtomicU8 里的两位。Mutex<T>、FairMutex<T>、ReentrantMutex<T> 都是 lock_api 泛型外壳的类型别名,parking_lot 这一层只写「原始锁怎么加、怎么解」,守卫体系全在 lock_api(06 lock_api)。
flowchart TB m["Mutex<T> = lock_api::Mutex<RawMutex, T>"] --> rm["RawMutex:AtomicU8,LOCKED_BIT / PARKED_BIT"] fm["FairMutex<T> = lock_api::Mutex<RawFairMutex, T>"] --> rfm["RawFairMutex(RawMutex):unlock 换成 unlock_fair"] --> rm re["ReentrantMutex<T> = lock_api::ReentrantMutex<RawMutex, RawThreadId, T>"] --> rrm["RawReentrantMutex:owner + lock_count"] --> rm rm -->|"lock_slow:park(addr)"| core["parking_lot_core 停车场"] rm -->|"unlock_slow:unpark_one(addr, 回调)"| core cv["Condvar"] -.->|"requeue 时直接改 PARKED_BIT"| rm
四章:
- RawMutex 的一字节状态机:四种状态与「锁被持有时
PARKED_BIT只在桶锁里清」的不变量;快路径各一次 CAS;lock_slow的抢、转、置位、停车;unlock_slow在桶锁里的回调怎样决定交接(TOKEN_HANDOFF)还是放开;给Condvar用的mark_parked_if_locked;没有毒化。 - 公平解锁、bump 与 FairMutex:
unlock_fair与unlock只差一个参数;bump有人等才让;FairMutex只换了unlock;最终公平的兜底效果与公平的代价(E3)。 - ReentrantMutex:lock_api 的
owner+lock_count,parking_lot 用线程局部变量的地址当线程 id;守卫只给&T、恒为!Send。 - 和 std Mutex 比:std 在 Linux 上是 futex、在 macOS 上是懒分配的 pthread mutex;大小表(E1);本机 0.12.5 / std / 0.13.0 三列吞吐与尾延迟(E2)。
一次有竞争的加锁在两侧(锁和停车场)怎么交替,全景时序图在 一次有竞争的加锁;停车场一侧的 park / unpark_one 在 park 与四种 unpark。
三种锁对照
Mutex | FairMutex | ReentrantMutex | |
|---|---|---|---|
| 原始锁 | RawMutex | RawFairMutex(RawMutex) | RawReentrantMutex<RawMutex, RawThreadId> |
本机 size_of::<_<()>>() | 1 | 1 | 24 |
| 普通解锁 | 插队允许,桶计时器 0–1 ms 兜底一次交接 | 有人停车就交接 | 计数归零时同 Mutex |
| 同线程再加锁 | 卡死 | 卡死 | 计数加一 |
| 守卫给出 | &mut T | &mut T | 只有 &T |
守卫 Send | 看 send_guard feature | 看 send_guard feature | 永不 |
能配 Condvar | 能 | 不能(守卫类型不同) | 不能 |
| 毒化 | 无 | 无 | 无 |
本部分的实验
| # | 目录 | 看什么 | 章 |
|---|---|---|---|
| E1 | exp-parking_lot/sizes/ | 本机 size_of 表;Linux 两个目标上 std 的大小用编译期断言核实 | 和 std Mutex 比 |
| E2 | exp-parking_lot/mutex-throughput/、v013-mutex-throughput/ | 0.12.5 / std / 0.13.0 的 ns/op 与单次 lock() 的 p50 / p99 / p99.9 | 和 std Mutex 比 |
| E3 | exp-parking_lot/eventual-fairness/、v013-eventual-fairness/ | 最长连续独占次数;持锁 1 µs 到 10 ms 五档;unlock_fair / FairMutex 的代价 | 公平解锁、bump 与 FairMutex |
计时类 crate 都去掉了 base 模板里的 deadlock_detection feature:开着它,每次加解锁都多一次线程局部记账(死锁检测)。
💬 关联讨论
发起讨论加载中...