用 std::mutex 就够了,它跨平台高效且基于原生互斥原语实现;慎用 std::recursive_mutex,因其开销大、可移植性差;绝大多数场景选 std::lock_guard,仅在需延迟加锁或配合条件变量时用 std::unique_lock。

用 std::mutex 就够了,别自己封装平台 API
标准库的 std::mutex 在所有主流编译器(GCC、Clang、MSVC)和操作系统(Linux、macOS、Windows)上都基于原生互斥原语实现,不是模拟出来的。它背后调用的是 pthread_mutex_t(POSIX)或 CreateMutex(Windows),但你完全不用关心——只要编译器支持 C++11 及以上,std::mutex 就是跨平台且高效的。
常见错误是看到 “Windows 有 CRITICAL_SECTION,Linux 有 pthread_mutex” 就想手动抽象一层,结果引入竞态、泄漏或死锁。比如有人写 MyCrossPlatformMutex 类,在 Windows 下忘了调用 InitializeCriticalSection,或者在析构时漏掉 pthread_mutex_destroy,这类 bug 很难复现。
- 确保编译选项启用 C++11 或更高:GCC/Clang 加
-std=c++11,MSVC 默认开启(VS2015+) - 不要对
std::mutex做 memcpy、赋值或拷贝构造——它是不可复制的,否则编译直接报错:use of deleted function - 避免全局或静态
std::mutex的初始化顺序问题;如果必须用,优先用局部静态变量 + 函数封装
为什么 std::recursive_mutex 要慎用
递归锁允许同一线程多次加锁,看似方便,实则掩盖设计缺陷。跨平台下它的开销比 std::mutex 明显更高:Linux 上要走完整的 futex 路径并维护持有者 tid 计数,Windows 上需额外查询线程 ID 并维护引用计数。
典型误用场景:把一个本该拆成多个独立临界区的函数,全包进一个递归锁里,结果让其他线程长时间阻塞。更隐蔽的问题是,某些嵌入式或精简版 STL 实现(如某些 Android NDK 版本)压根不提供 std::recursive_mutex,导致编译失败。
立即学习“C++免费学习笔记(深入)”;
- 优先用
std::mutex+ 明确的锁粒度划分(比如按数据成员分锁) - 真需要递归语义,考虑用
std::unique_lock<:mutex></:mutex>配合作用域控制,而不是依赖递归锁本身 - 若必须用,检查目标平台 STL 是否支持:Clang libc++ 和 GNU libstdc++ 都支持,但旧版 MinGW-w64 的 libstdc++ 可能不完整
std::lock_guard 和 std::unique_lock 到底选哪个
std::lock_guard 是最轻量的 RAII 封装,构造即加锁、析构即解锁,没多余开销,适合绝大多数“进函数加锁、出函数解锁”的场景。而 std::unique_lock 支持延迟加锁、条件变量配合、转移所有权,但也多了布尔状态判断和可能的原子操作。
容易踩的坑是:以为 std::unique_lock 更“高级”就默认用它,结果在 hot path 里多出几十个周期——尤其在高并发短临界区场景下,性能差异可测出 5%~10%。
- 95% 的情况用
std::lock_guard<:mutex></:mutex>,简洁、零成本、不易出错 - 只在以下情况才换
std::unique_lock:要调用cv.wait()、需要try_lock()、或要把锁对象传给另一个函数 - 别写
std::unique_lock<:mutex> lk(mtx, std::defer_lock)</:mutex>然后手动lk.lock()——这等于放弃 RAII 优势,和裸调mtx.lock()差不多危险
跨平台时绝对不能碰的几个东西
有些看似“通用”的同步机制,实际在平台间行为不一致,或者根本不可靠。比如 std::atomic_flag 虽然跨平台,但它只保证 test-and-set,没法替代互斥锁做复杂临界区保护;又比如 Windows 的 SRWLock 和 Linux 的 pthread_rwlock_t,虽然都叫读写锁,但前者不支持递归读取,后者在某些 glibc 版本里有唤醒饥饿问题。
还有人试图用文件锁(flock / LockFileEx)做进程内同步,结果在 NFS 或容器环境下完全失效——这些根本不是为线程同步设计的。
- 坚持用
std::mutex/std::shared_mutex(C++17)做线程同步,别绕路 -
std::shared_mutex跨平台支持较新:MSVC 2019 16.6+、GCC 10+、Clang 12+ 才稳定,旧环境别硬上 - 避免
#ifdef _WIN32手动切换锁类型——这会让代码难以测试,也违背“用标准设施解决标准问题”的前提










