std :: unique_lock <std :: mutex>或std :: lock_guard <std :: mutex>?
我有两个用例。
答:我想通过两个线程同步访问队列。
B.我想通过两个线程同步访问一个队列,并使用一个条件variables,因为其中一个线程将等待内容被另一个线程存储到队列中。
对于用例AI,请参阅使用std::lock_guard<>
代码示例。 对于用例BI,请参阅使用std::unique_lock<>
代码示例。
两者之间有什么区别,哪一个应该在哪个用例中使用?
不同的是,你可以locking和解锁std::unique_lock
。 std::lock_guard
只会在施工时locking一次,并在销毁时解锁。
所以对于用例B,你肯定需要一个std::unique_lock
作为条件variables。 在情况A这取决于你是否需要重新locking警卫。
std::unique_lock
还有其他一些特性,例如:可以在不立即locking互斥体的情况下构build,而是构buildRAII包装器(请参见这里 )。
std::lock_guard
也提供了一个方便的RAII包装,但不能安全地locking多个互斥锁。 当你需要一个有限范围的包装时,可以使用它,例如:一个成员函数:
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 (eg 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
replacestd::lock_guard
。 但是, std::unique_lock
可能会有更多的开销。
lock_guard
和unique_lock
几乎是一回事; lock_guard
是一个受限制的界面。
lock_guard
总是保持从其构build到销毁的locking。 unique_lock
可以在不立即locking的情况下创build,可以在其存在的任何时候解锁,并且可以将锁的所有权从一个实例转移到另一个实例。
所以你总是使用lock_guard
,除非你需要unique_lock
的function。 condition_variable
需要一个unique_lock
。
使用lock_guard
除非您需要能够在不破坏lock
情况下手动unlock
互斥lock
。
特别是, condition_variable
在wait
呼叫时睡眠时释放它的互斥量。 这就是为什么lock_guard
在这里是不够的。
lock_guard和unique_lock之间有一些共同的东西,还有一些不同之处。 但是在提出的问题的上下文中,编译器不允许将lock_guard与条件variables结合使用,因为当线程调用等待条件variables时,互斥锁会自动解锁,并且当其他线程/线程通知当前线程被调用(出来等待),锁被重新获得。 这种现象违背了lock_guard的原则。 lock_guard只能被构造一次,只能被破坏一次。
因此,lock_guard不能与条件variables结合使用,但unique_lock可以是(因为unique_lock可以被locking和解锁多次)。
正如其他人所提到的那样,std :: unique_lock跟踪互斥锁的locking状态,所以你可以推迟locking,直到locking构造完成,并且在locking破坏之前解锁。 std :: lock_guard不允许这样做。
似乎没有理由为什么std :: condition_variable等待函数不应该使用lock_guard以及unique_lock,因为无论何时等待结束(无论什么原因),互斥体都会自动重新获取,从而不会导致任何语义违规。 然而根据标准,要使用带有条件variables的std :: lock_guard,则必须使用std :: condition_variable_any而不是std :: condition_variable。
编辑 :删除“使用pthreads接口std :: condition_variable和std :: condition_variable_any应该是相同的”。 在看gcc的实现:
- std :: condition_variable :: wait(std :: unique_lock&)只是调用基础pthread条件variables的pthread_cond_wait()与unique_lock所持有的互斥锁有关(对lock_guard也是如此,但是并不是因为标准没有规定)
- std :: condition_variable_any可以和任何可locking的对象一起工作,包括一个根本不是互斥锁的对象(因此它甚至可以和一个进程间的信号一起工作)