一、开场:一行lock_guard换来 11 毫秒
凌晨两点的性能会议。
一张火焰图打在屏幕上:音频线程的耗时 P99 是11.3ms。
而音频驱动给的交付窗口是10ms。于是每隔几十秒,玩家耳朵里就会炸开一声"啪"。
有人指着那根刺眼的柱子问:“这里为什么这么长?”
答案是一行谁都不觉得有问题的代码:
std::lock_guard<std::mutex> lock(audioMutex); // 等主线程放手音频线程,一个优先级最高的实时线程,被一个正在小核上打日志的主线程,锁在门外 11 毫秒。
这篇文章讲的,就是怎么让这扇门根本不存在。
二、锁到底贵在哪:不是平均慢,是尾部炸
大多数人对锁的印象是"慢"。这个印象是错的——无争用的互斥锁只要 20~50ns,比你想象中快得多。
锁真正致命的是另外三件事。
2.1 罪状一:P99 爆炸,而不是平均值变慢
无争用: 25 ns ← 99% 的情况 有争用: 1,000 ns ← 上下文切换 最坏情况:11,000,000 ns ← 持锁者被调度器切走了<