在C++并发编程中,当多个线程需要访问同一个共享资源时,很容易出现数据竞争的情况,比如两个线程同时对一个全局变量做加一操作,最终的结果可能和预期不符。这时候就需要用到互斥锁来保证同一时间只有一个线程能够访问共享资源,mutex就是C++标准库提供的互斥锁实现。

mutex互斥锁的基本用法
mutex是C++11引入的<mutex>头文件中定义的类,它的核心作用是保证临界区的互斥访问。使用mutex的基本流程是:在访问共享资源前调用lock()方法加锁,访问完成后调用unlock()方法解锁。如果当前mutex已经被其他线程加锁,那么调用lock()的线程会被阻塞,直到锁被释放。
下面是一个简单的示例,模拟两个线程同时对一个全局变量做加一操作,使用mutex保证操作的正确性:
#include <iostream>
#include <thread>
#include <mutex>
// 共享资源
int shared_counter = 0;
// 定义互斥锁
std::mutex mtx;
// 线程执行的函数,对共享变量加10000次
void increment_counter() {
for (int i = 0; i < 10000; i++) {
// 加锁,获取互斥锁所有权
mtx.lock();
shared_counter++;
// 解锁,释放互斥锁
mtx.unlock();
}
}
int main() {
// 创建两个线程
std::thread t1(increment_counter);
std::thread t2(increment_counter);
// 等待两个线程执行完成
t1.join();
t2.join();
// 输出最终结果,预期是20000
std::cout << "shared_counter final value: " << shared_counter << std::endl;
return 0;
}
如果去掉加锁和解锁的逻辑,两个线程同时操作shared_counter时,可能出现读取到旧值、写入覆盖的情况,最终结果会小于20000。
使用lock_guard简化锁管理
直接使用mutex的lock()和unlock()方法有一个风险:如果在临界区中抛出了异常,或者中途提前返回,就可能导致unlock()没有被调用,引发死锁。为了避免这个问题,C++标准库提供了std::lock_guard模板类,它会在构造时自动加锁,析构时自动解锁,不需要手动调用unlock()。
使用lock_guard改写上面的示例:
#include <iostream>
#include <thread>
#include <mutex>
int shared_counter = 0;
std::mutex mtx;
void increment_counter() {
for (int i = 0; i < 10000; i++) {
// 构造lock_guard对象,自动加锁
std::lock_guard<std::mutex> lock(mtx);
shared_counter++;
// lock对象析构时自动解锁,即使这里抛出异常也不会死锁
}
}
int main() {
std::thread t1(increment_counter);
std::thread t2(increment_counter);
t1.join();
t2.join();
std::cout << "shared_counter final value: " << shared_counter << std::endl;
return 0;
}
lock_guard的使用非常简单,只需要把mutex对象作为参数传入它的构造函数即可,作用域结束时会自动释放锁,大大降低了死锁的风险。
mutex使用的注意事项
- 不要重复对同一个mutex调用lock()方法,同一线程重复加锁会导致死锁,这种情况可以使用
std::recursive_mutex递归互斥锁。 - 加锁的粒度要尽量小,只把访问共享资源的代码放在临界区中,避免锁持有时间过长影响并发性能。
- 如果多个线程需要同时获取多个互斥锁,要使用
std::lock()函数同时加锁,避免死锁,配合std::adopt_lock参数使用lock_guard管理锁。
多锁同时获取示例
当两个线程需要同时获取两个互斥锁时,直接分别调用lock()很容易出现死锁,比如线程1先锁mtx1再锁mtx2,线程2先锁mtx2再锁mtx1,就可能互相等待。这时候可以用std::lock()同时加锁:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx1;
std::mutex mtx2;
void thread_func1() {
// 同时锁两个互斥锁,避免死锁
std::lock(mtx1, mtx2);
// 使用adopt_lock参数,表示锁已经被获取,lock_guard不会再重复加锁,只负责析构时解锁
std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);
std::cout << "thread 1 get both locks" << std::endl;
}
void thread_func2() {
std::lock(mtx1, mtx2);
std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);
std::cout << "thread 2 get both locks" << std::endl;
}
int main() {
std::thread t1(thread_func1);
std::thread t2(thread_func2);
t1.join();
t2.join();
return 0;
}
以上就是C++中mutex互斥锁的基本使用方法,掌握这些技巧就能应对大部分并发场景下的资源同步问题。
C++_concurrencymutexthread_synchronizationlock_guard修改时间:2026-06-29 18:21:30