Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;11:为什么std::condition\u变量使用std::unique\u锁?_C++_Multithreading_C++11_Mutex - Fatal编程技术网

C++ C++;11:为什么std::condition\u变量使用std::unique\u锁?

C++ C++;11:为什么std::condition\u变量使用std::unique\u锁?,c++,multithreading,c++11,mutex,C++,Multithreading,C++11,Mutex,在使用std::condition\u变量时,我对std::unique\u lock的角色有点困惑。据我所知,std::unique_lock基本上是一个膨胀的锁保护,可以在两个锁之间交换状态 到目前为止,我使用了pthread\u cond\u wait(pthread\u cond\u t*cond,pthread\u mutex\u t*mutex)来实现这个目的(我想这就是STL在posix上使用的)。它需要一个互斥锁,而不是锁 这里有什么区别?std::condition\u var

在使用
std::condition\u变量时,我对
std::unique\u lock
的角色有点困惑。据我所知,
std::unique_lock
基本上是一个膨胀的锁保护,可以在两个锁之间交换状态

到目前为止,我使用了
pthread\u cond\u wait(pthread\u cond\u t*cond,pthread\u mutex\u t*mutex)
来实现这个目的(我想这就是STL在posix上使用的)。它需要一个互斥锁,而不是锁


这里有什么区别?
std::condition\u variable
处理
std::unique\u lock
这一事实是否是一种优化?如果是这样的话,它到底有多快?

这本质上是一个API设计决策,在默认情况下使API尽可能安全(额外的开销可以忽略不计)。通过要求传递
唯一锁
而不是原始的
互斥锁
,API用户将被引导编写正确的代码(在存在异常的情况下)

近年来,C++语言的焦点已经转向了默认的安全性(但是如果用户愿意和努力的话,仍然允许用户自己射击)。
所以没有技术上的原因

我对cmeerw的答案投了赞成票,因为我相信他给出了一个技术上的理由。让我们走过去。让我们假设委员会决定让
条件变量
等待
互斥锁
。下面是使用该设计的代码:

void foo()
{
    mut.lock();
    // mut locked by this thread here
    while (not_ready)
        cv.wait(mut);
    // mut locked by this thread here
    mut.unlock();
}
这正是不应该使用
条件变量的方法。在标有以下标记的区域:

// mut locked by this thread here
存在异常安全问题,这是一个严重的问题。如果在这些区域(或通过
cv.wait
本身)引发异常,则互斥锁的锁定状态将泄漏,除非还将try/catch放在某个位置以捕获异常并将其解锁。但这只是要求程序员编写的更多代码

假设程序员知道如何编写异常安全代码,并且知道如何使用
unique\u lock
来实现它。现在代码如下所示:

void foo()
{
    unique_lock<mutex> lk(mut);
    // mut locked by this thread here
    while (not_ready)
        cv.wait(*lk.mutex());
    // mut locked by this thread here
}
  • 这段代码非常简单
  • 它是异常安全的
  • wait
    函数可以检查
    lk.owners\u lock()
    并在异常为
    false
    时抛出异常
  • 这些是推动
    条件变量
    的API设计的技术原因

    另外,
    condition\u variable::wait
    不接受
    lock\u guard
    ,因为
    lock\u guard
    是这样说的:我拥有这个互斥锁,直到
    lock\u guard
    销毁。但是当您调用
    条件变量::wait
    时,会隐式释放互斥锁。因此,该操作与
    lock\u guard
    用例/语句不一致

    无论如何,我们需要
    unique\u lock
    ,这样就可以从函数返回锁,将它们放入容器中,并以异常安全的方式在非作用域模式中锁定/解锁互斥锁,因此
    unique\u lock
    条件变量::wait
    的自然选择

    更新

    bamboon在下面的评论中建议我对比
    条件变量\u any
    ,因此:

    问题:为什么不将
    条件变量::wait
    模板化,以便我可以将任何
    可锁定的
    类型传递给它

    回答:

    这是非常酷的功能。例如,演示了在条件变量的共享模式下等待
    共享锁
    (rwlock)的代码(posix世界中闻所未闻,但非常有用)。但是,功能更昂贵

    因此,委员会推出了一种具有此功能的新型:

    `condition_variable_any`
    
    使用此
    条件变量
    适配器,您可以等待任何可锁定类型。如果它有成员
    lock()
    unlock()
    ,您就可以开始了。
    condition\u variable\u any
    的正确实现需要一个
    condition\u variable
    数据成员和一个
    shared\u ptr
    数据成员


    因为这个新功能比基本的
    条件变量::wait
    更昂贵,而且
    条件变量
    是一个低级工具,这个非常有用但更昂贵的功能被放在一个单独的类中,因此只有在您使用它时才需要付费。

    您是否对为什么需要带条件变量的锁/互斥锁、锁和互斥锁之间的区别或者为什么条件变量使用唯一的锁而不是互斥锁感到困惑?“为什么条件变量使用唯一锁而不是互斥锁”这句话。所以没有技术上的原因?你能澄清一下“它”吗“。您是在谈论
    锁紧保护
    ,还是
    条件变量
    ,或者可能是
    条件变量::等待
    ?对不起,忘了它。我完全忘记了
    condition\u variable\u any
    Ah,模板
    condition\u variable::wait
    。是的,
    condition\u variable\u any
    是一个不错的选择。功能没有被折叠到
    条件变量中的原因是它更昂贵。而
    condition\u variable
    是一个非常低级的工具,它需要尽可能高效。如果您使用
    条件变量\u any
    ,您只需为添加的功能付费。好的,谢谢您提供的额外信息。也许可以在你的答案中加上这一点,因为人们可能会用一个简单的互斥锁误用
    条件变量。\u any
    。哇,我被你的答案吓坏了。非常感谢您提供如此详细的信息!
    `condition_variable_any`