std::lock_guard
和 std::unique_lock
都是 C++11 中提供的用于互斥锁管理的工具,它们在许多方面是相似的,但也存在一些关键的区别:
std::lock_guard
-
自动管理:
std::lock_guard
是一个作用域锁(scoped lock),它会在构造时自动锁定互斥量,并在析构时自动解锁。因此,它是一种简单、安全的互斥量管理方式,可以防止忘记解锁。 -
不可转移:
std::lock_guard
不支持所有权转移,即你不能将一个std::lock_guard
对象传递给另一个std::lock_guard
对象。 -
不可解锁:一旦
std::lock_guard
锁定了互斥量,就不能再解锁它,直到std::lock_guard
对象被销毁。 -
性能:由于
std::lock_guard
功能较为简单,因此它的性能开销通常比std::unique_lock
小。
std::unique_lock
-
灵活管理:
std::unique_lock
提供了更多的灵活性。它可以手动锁定和解锁互斥量,还可以在构造时选择是否立即锁定。 -
可转移:
std::unique_lock
支持所有权转移,可以通过std::move
操作将锁的所有权从一个std::unique_lock
对象转移到另一个。 -
可解锁:
std::unique_lock
可以随时解锁和重新锁定互斥量。 -
条件变量:
std::unique_lock
可以与std::condition_variable
一起使用,而std::lock_guard
不可以。 -
性能:由于
std::unique_lock
提供了更多的功能,它的性能开销可能会比std::lock_guard
大。
示例比较
下面是一个简单的例子,展示 std::lock_guard
和 std::unique_lock
的用法:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void print_with_lock_guard() {
std::lock_guard<std::mutex> lg(mtx);
std::cout << "Printing with lock_guard..." << std::endl;
// mtx.unlock(); // 错误:不能手动解锁
}
void print_with_unique_lock() {
std::unique_lock<std::mutex> ul(mtx);
std::cout << "Printing with unique_lock..." << std::endl;
ul.unlock(); // 可以手动解锁
// Do some other work without holding the lock
ul.lock(); // 可以手动锁定
std::cout << "Locking again with unique_lock..." << std::endl;
}
int main() {
std::thread t1(print_with_lock_guard);
std::thread t2(print_with_unique_lock);
t1.join();
t2.join();
return 0;
}
在大多数情况下,如果不需要 std::unique_lock
提供的额外灵活性,建议使用 std::lock_guard
,因为它更简单且易于使用。如果需要更高级的锁定控制,比如需要在锁定和解锁之间执行其他操作,或者需要与条件变量一起使用,那么 std::unique_lock
是更好的选择。