std::unique_lock
是 C++11 标准库中的一个类,提供了一种灵活的方式来管理互斥量(mutex)。
它比 std::lock_guard
更加灵活,允许在不同的作用域和不同的锁定策略之间进行选择。以下是对 unique_lock
的详细解释,包括其用途、使用方法和优点。
1. 定义
std::unique_lock
是一种 RAII(资源获取即初始化)风格的锁,它在构造时锁定给定的互斥量,并在析构时自动解锁。这确保了在离开作用域时,锁会被自动释放,从而避免死锁。
2. 用途
- 用于保护共享资源,确保在多线程环境中,只有一个线程能够访问该资源。
- 适合需要在多个地方手动控制锁定与解锁的场景,例如在条件变量中使用。
- 可以与
std::condition_variable
一起使用,以便在等待条件变量时自动管理锁。
3. 如何使用
以下是使用 std::unique_lock
的基本步骤和示例代码:
示例代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cond_var;
int shared_data = 0;
void producer() {
std::unique_lock<std::mutex> lock(mtx); // 锁定互斥量
shared_data = 42; // 修改共享数据
std::cout << "Produced: " << shared_data << std::endl;
cond_var.notify_one(); // 通知消费者
} // 离开作用域时自动解锁
void consumer() {
std::unique_lock<std::mutex> lock(mtx); // 锁定互斥量
cond_var.wait(lock, [] { return shared_data != 0; }); // 等待条件变量
std::cout << "Consumed: " << shared_data << std::endl;
} // 离开作用域时自动解锁
int main() {
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
return 0;
}
4. 为什么要用它
-
灵活性:与
std::lock_guard
相比,std::unique_lock
提供了更多的灵活性,支持以下功能:- 可以在构造时选择是否锁定互斥量。
- 支持手动锁定和解锁:可以在需要时调用
lock()
和unlock()
方法。 - 支持条件变量的等待:在等待条件变量时,可以传入
unique_lock
,并在条件满足时自动解锁和重新锁定。
-
避免死锁:由于
std::unique_lock
的 RAII 特性,确保在作用域结束时自动解锁,降低了因忘记解锁而引起死锁的风险。 -
可以延迟锁定:你可以在构造
unique_lock
时不锁定互斥量,并在后面需要时再手动锁定。
5. 总结
std::unique_lock
是一种灵活且安全的互斥量管理方式,适合在复杂的多线程环境中使用。
它不仅简化了锁的管理,还减少了编程错误的可能性,尤其是在涉及条件变量和复杂的锁定策略时。