std::lock_guard
是 C++ 标准库中的一个类模板,用于简化互斥量(mutex)的管理。它通过 RAII(Resource Acquisition Is Initialization)机制,在构造时锁定互斥量,在析构时自动解锁互斥量,从而确保即使在异常情况下也能正确地释放锁。
std::lock_guard
在构造时获取锁,在析构时释放锁,减少了手动管理锁的复杂性和潜在的错误。lock()
和 unlock()
,使用 std::lock_guard
可以使代码更加简洁和易读。std::lock_guard
适用于需要简单锁管理的场景,特别是当锁的持有时间较短且不需要复杂的锁操作时。它通常与 std::mutex
或其派生类一起使用。
以下是一个在函数中创建多个 std::lock_guard
的示例:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx1;
std::mutex mtx2;
void threadFunc(int id) {
std::lock_guard<std::mutex> lock1(mtx1);
std::cout << "Thread " << id << " acquired mtx1" << std::endl;
std::lock_guard<std::mutex> lock2(mtx2);
std::cout << "Thread " << id << " acquired mtx2" << std::endl;
// 模拟一些工作
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Thread " << id << " releasing locks" << std::endl;
}
int main() {
std::thread t1(threadFunc, 1);
std::thread t2(threadFunc, 2);
t1.join();
t2.join();
return 0;
}
原因:当多个线程以不同的顺序获取多个锁时,可能会导致死锁。例如,线程 A 获取了锁1并尝试获取锁2,而线程 B 获取了锁2并尝试获取锁1。
解决方法:
std::scoped_lock
:std::scoped_lock
可以一次性获取多个锁,并保证不会发生死锁。示例代码(使用 std::scoped_lock
):
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx1;
std::mutex mtx2;
void threadFunc(int id) {
std::scoped_lock lock(mtx1, mtx2);
std::cout << "Thread " << id << " acquired both locks" << std::endl;
// 模拟一些工作
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Thread " << id << " releasing locks" << std::endl;
}
int main() {
std::thread t1(threadFunc, 1);
std::thread t2(threadFunc, 2);
t1.join();
t2.join();
return 0;
}
通过使用 std::scoped_lock
,可以避免手动管理多个锁时可能出现的死锁问题。
std::lock_guard
是一个简单且有效的工具,用于管理互斥量的生命周期。在多线程编程中,合理使用 std::lock_guard
可以提高代码的安全性和可读性。当需要同时管理多个锁时,推荐使用 std::scoped_lock
以避免死锁问题。
云+社区沙龙online [云原生技术实践]
云+社区技术沙龙[第22期]
云+社区沙龙online第6期[开源之道]
腾讯技术开放日
TVP技术夜未眠
小程序·云开发官方直播课(数据库方向)
云+社区技术沙龙[第14期]
云+社区沙龙online
云+社区技术沙龙[第27期]
领取专属 10元无门槛券
手把手带您无忧上云