std::mutex用于保护共享数据,配合std::lock_guard或std::unique_lock实现线程安全;示例展示两个线程对计数器加锁递增,确保结果正确;std::lock_guard自动管理锁生命周期,防止死锁;std::unique_lock支持延迟加锁和手动控制,适用于复杂场景;使用std::lock和固定顺序获取多把锁可避免死锁;合理控制临界区大小以提升性能。

在C++多线程编程中,std::mutex 是最常用的同步工具之一,用于保护共享数据,防止多个线程同时访问造成数据竞争。它定义在
基本用法:保护共享资源
当多个线程需要修改同一个变量时,必须使用互斥锁来串行化访问。例如,两个线程同时对一个全局计数器进行递增操作,若不加锁,可能导致结果错误。
示例代码:
#include zuojiankuohaophpcniostreamyoujiankuohaophpcn
#include zuojiankuohaophpcnthreadyoujiankuohaophpcn
#include zuojiankuohaophpcnmutexyoujiankuohaophpcn
int counter = 0;
std::mutex mtx; // 定义互斥锁
void increment() {
for (int i = 0; i zuojiankuohaophpcn 100000; ++i) {
std::lock_guardzuojiankuohaophpcnstd::mutexyoujiankuohaophpcn lock(mtx); // 自动加锁/解锁
++counter;
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout zuojiankuohaophpcnzuojiankuohaophpcn "Final counter value: " zuojiankuohaophpcnzuojiankuohaophpcn counter zuojiankuohaophpcnzuojiankuohaophpcn std::endl;
return 0;
}在这个例子中,std::lock_guard 在构造时自动加锁,析构时自动释放锁,避免了忘记解锁导致的死锁问题。
立即学习“C++免费学习笔记(深入)”;
std::unique_lock 的灵活控制
相比 std::lock_guard,std::unique_lock 提供了更多灵活性,比如可以延迟加锁、手动控制加锁与解锁时机,甚至支持条件变量。
示例:手动控制锁的范围
std::mutex mtx; std::unique_lockzuojiankuohaophpcnstd::mutexyoujiankuohaophpcn lock(mtx, std::defer_lock); // 不立即加锁 // ... 做一些不需要锁的操作 lock.lock(); // 手动加锁 // 访问共享资源 ++counter; lock.unlock(); // 可以提前释放锁
这种机制适合在临界区较短或需要在加锁前后执行其他操作的场景。
避免死锁的常见技巧
多个互斥锁同时使用时容易发生死锁。例如线程A持有锁1并等待锁2,而线程B持有锁2并等待锁1。
解决方法包括:
- 始终以相同的顺序获取多个锁
- 使用 std::lock 一次性锁定多个互斥量,避免中间状态
示例:安全地锁定两个互斥量
std::mutex mtx1, mtx2;
void thread_func() {
std::lock(mtx1, mtx2); // 同时尝试获取两个锁
std::lock_guardzuojiankuohaophpcnstd::mutexyoujiankuohaophpcn lock1(mtx1, std::adopt_lock);
std::lock_guardzuojiankuohaophpcnstd::mutexyoujiankuohaophpcn lock2(mtx2, std::adopt_lock);
// 使用共享资源
}这里 std::adopt_lock 表示构造 lock_guard 时不重新加锁,而是接管已持有的锁。
基本上就这些。只要合理使用 std::mutex 配合 RAII 风格的锁管理,就能写出安全高效的并发程序。关键是把临界区控制得越小越好,避免长时间持锁影响性能。











