std::lock_guard<std::mutex>
是 C++11 引入的一种 RAII(资源获取即初始化)风格的锁管理器,用于简化互斥锁的管理,确保在离开作用域时自动释放锁,避免死锁。以下是对 std::lock_guard<std::mutex>
的详细解释:
1. 基本用法
cpp
#include <iostream>
#include <mutex>
std::mutex mutex_;
void safe_function() {
std::lock_guard<std::mutex> lock(mutex_); // 获取锁
// 临界区代码
std::cout << "Inside critical section" << std::endl;
} // lock 在这里被销毁,自动释放锁
在上述代码中,std::lock_guard<std::mutex>
的构造函数会自动获取 mutex_
的锁,当 lock
离开作用域时(即函数结束时),其析构函数会自动释放锁。
2. 作用
- 自动加锁和解锁 :
std::lock_guard
的构造函数会自动加锁,析构函数会自动解锁。 - 防止死锁:通过确保锁在作用域结束时自动释放,避免因忘记解锁而导致的死锁问题。
- 异常安全:即使在临界区发生异常,锁也会在作用域结束时自动释放。
3. 成员函数
std::lock_guard
没有公开的成员函数,它的操作主要通过构造函数和析构函数完成。
4. 示例代码
以下是一个完整的示例,展示了如何使用 std::lock_guard
来保护共享资源:
cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
std::mutex mutex_;
int shared_resource = 0;
void increment() {
for (int i = 0; i < 1000; ++i) {
std::lock_guard<std::mutex> lock(mutex_); // 获取锁
++shared_resource;
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Final value: " << shared_resource << std::endl; // 输出 2000
return 0;
}
在上述代码中,两个线程同时访问和修改共享资源 shared_resource
,通过 std::lock_guard
确保每次只能有一个线程进入临界区,从而避免数据竞争。
5. 与其他锁管理器的比较
std::lock_guard
:简单,自动管理锁,适合大多数场景。std::unique_lock
:功能更强大,支持延迟加锁、解锁、移动语义等,但稍微复杂一些。
6. 底层机制
std::lock_guard
的构造函数调用 std::mutex
的 lock()
方法,析构函数调用 std::mutex
的 unlock()
方法。这确保了即使在异常情况下,锁也能被正确释放。
7. 总结
std::lock_guard<std::mutex>
是一种简单的 RAII 风格的锁管理器。- 它确保在进入作用域时自动加锁,在离开作用域时自动解锁。
- 它非常适合保护临界区,避免死锁和数据竞争。
- 在需要更复杂的功能时,可以考虑使用
std::unique_lock
。
通过使用 std::lock_guard
,可以显著提高代码的安全性和可维护性。