我有两个用例。std :: unique_lock <std::mutex>或std :: lock_guard <std::mutex>?
答:我想通过两个线程同步访问队列。
B.我想通过两个线程将访问同步到一个队列并使用一个条件变量,因为其中一个线程将等待内容被其他线程存储到队列中。
对于用例A,我看到使用std::lock_guard<>
的代码示例。对于用例B,我使用std::unique_lock<>
来查看代码示例。
两者之间有什么区别,哪一个应该在哪个用例中使用?
我有两个用例。std :: unique_lock <std::mutex>或std :: lock_guard <std::mutex>?
答:我想通过两个线程同步访问队列。
B.我想通过两个线程将访问同步到一个队列并使用一个条件变量,因为其中一个线程将等待内容被其他线程存储到队列中。
对于用例A,我看到使用std::lock_guard<>
的代码示例。对于用例B,我使用std::unique_lock<>
来查看代码示例。
两者之间有什么区别,哪一个应该在哪个用例中使用?
区别在于你可以锁定和解锁std::unique_lock
。 std::lock_guard
只会在施工时锁定一次,并在销毁时解锁。
因此,对于用例B,您肯定需要std::unique_lock
作为条件变量。在情况A这取决于你是否需要重新锁定警卫。
std::unique_lock
还有其他一些功能,例如:构建时不立即锁定互斥锁,而是构建RAII封装(请参见here)。
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
除非您需要能够在不破坏lock
的情况下手动unlock
互斥体。
特别是,condition_variable
在呼叫wait
时睡觉时会解锁其互斥锁。这就是为什么lock_guard
在这里是不够的。
将lock_guard传递给其中一个条件变量的等待方法会很好,因为无论出于何种原因,等待结束时总会重新获取互斥锁。但是该标准仅为unique_lock提供了一个接口。这可能被认为是标准的一个缺陷。 –
@Chris在这种情况下你仍然会破坏封装。等待方法需要能够从'lock_guard'中提取互斥并解除锁定,从而暂时打破守护的类不变。即使这种情况对用户不可见,但我认为在这种情况下不允许使用'lock_guard'的合理原因。 – ComicSansMS
如果是这样,它将是不可见的,无法检测。 gcc-4.8做到了。 wait(unique_lock
lock_guard
和unique_lock
几乎是一回事; lock_guard
是一个限制版本,界面有限。
A lock_guard
始终保持从其施工到销毁的锁定。可以在不立即锁定的情况下创建unique_lock
,可以在其存在的任何时候解锁,并且可以将锁的所有权从一个实例转移到另一个实例。
因此,您总是使用lock_guard
,除非您需要unique_lock
的功能。 A condition_variable
需要unique_lock
。
'condition_variable需要一个unique_lock.' - 只有在'wait()'方面是_but_,详细阐述在我的对inf的评论 –
正如其他人所提到的,std :: unique_lock跟踪互斥锁的锁定状态,因此您可以推迟锁定,直到锁定构建完成,然后在锁定破坏之前解除锁定。 std :: lock_guard不允许这样做。
似乎没有理由为什么std :: condition_variable等待函数不应该带一个lock_guard以及一个unique_lock,因为每当等待结束时(无论出于何种原因)互斥体都会自动重新获取以便不会导致任何语义违规。但是根据标准,要使用带条件变量的std :: lock_guard,必须使用std :: condition_variable_any而不是std :: condition_variable。
编辑:删除“使用pthreads接口std :: condition_variable和std :: condition_variable_any应该是相同的”。对望一眼,GCC的实现:
有一些共同的东西在lock_guard
和unique_lock
之间以及某些差异。
但是在提出的问题的上下文中,编译器不允许将lock_guard
与条件变量结合使用,因为当线程调用等待条件变量时,该互斥锁会自动解锁并在其他线程/线程通知并且当前线程被调用(等待),锁被重新获取。
这种现象违反了lock_guard
的原则。 lock_guard
只能构造一次,只能破坏一次。
因此lock_guard
不能与条件变量组合使用,但unique_lock
可以(因为unique_lock
可以被锁定和解锁多次)。
'他编译器不允许与条件变量结合使用lock_guard'这是错误的。它肯定**允许并且在notify()方面与'lock_guard'完美配合。只有'wait()'int方需要'unique_lock',因为'wait()'必须在检查条件时释放锁。 –
用指令std :: unique_lock lock(myMutex);互斥锁是否会被构造函数锁定? –
chmike
@chmike是的,它会的。补充说明。 – inf
如果我在使用情况A,使用lock_gard而不是unique_lock会更有效吗? – chmike