std :: unique_lock <std :: mutex>或std :: lock_guard <std :: mutex>?

我有两个用例。

答:我想通过两个线程同步访问队列。

B.我想通过两个线程同步访问一个队列,并使用一个条件variables,因为其中一个线程将等待内容被另一个线程存储到队列中。

对于用例AI,请参阅使用std::lock_guard<>代码示例。 对于用例BI,请参阅使用std::unique_lock<>代码示例。

两者之间有什么区别,哪一个应该在哪个用例中使用?

不同的是,你可以locking和解锁std::unique_lockstd::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_guardstd::unique_lock是一样的。 所以在上面的例子中,你可以用std::unique_lockreplacestd::lock_guard 。 但是, std::unique_lock可能会有更多的开销。

lock_guardunique_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_variablewait呼叫时睡眠时释放它的互斥量。 这就是为什么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的对象一起工作,包括一个根本不是互斥锁的对象(因此它甚至可以和一个进程间的信号一起工作)