锁<std :: mutex>或std :: lock
我有两个用例。
答:我想通过两个线程同步访问队列。
B.我想将两个线程的访问同步到一个队列中,并使用一个条件变量,因为其中一个线程将等待内容被另一个线程存储到队列中。
对于用例AI,请参阅使用std::lock_guard<>
代码示例。 对于用例BI,请参阅使用std::unique_lock<>
代码示例。
两者之间有什么区别,哪一个应该在哪个用例中使用?
区别在于你可以锁定和解锁std::unique_lock
。 std::lock_guard
只会在施工时锁定一次,并在破坏时解锁。
所以对于用例B,你肯定需要一个std::unique_lock
作为条件变量。 在情况A这取决于你是否需要重新锁定警卫。
std::unique_lock
还有其他一些特性,例如:构建时不立即锁定互斥锁,而是构建RAII包装器(请参见此处)。
std::lock_guard
也提供了一个方便的RAII包装,但不能安全地锁定多个互斥锁。 当你需要一个有限范围的包装时可以使用它,例如:一个成员函数:
class MyClass{
std::mutex my_mutex;
void member_foo() {
std::lock_guard<mutex_type> lock(this->my_mutex);
/*
block of code which needs mutual exclusion (e.g. open the same
file in multiple threads).
*/
//mutex is automatically released when lock goes out of scope
};
为了澄清由chmike提出的问题,默认情况下, std::lock_guard
和std::unique_lock
是相同的。 所以在上面的例子中,你可以用std::unique_lock
替换std::lock_guard
。 但是, std::unique_lock
可能会有更多的开销。
lock_guard
和unique_lock
几乎是一回事; lock_guard
是一个限制版本,界面有限。
lock_guard
总是保持从其构造到销毁的锁。 可以在不立即锁定的情况下创建unique_lock
,可以在其存在的任何时刻解锁,并且可以将锁的所有权从一个实例转移到另一个实例。
所以你总是使用lock_guard
,除非你需要unique_lock
的功能。 condition_variable
需要unique_lock
。
除非您需要能够在不破坏lock
情况下手动unlock
互斥锁,否则请使用lock_guard
。
特别是, condition_variable
在wait
呼叫时睡眠时释放它的互斥锁。 这就是为什么lock_guard
在这里不够用。