为什么std :: condition_variable采取unique_lock而不是lock_guard?

时间:2018-08-10 07:06:46

标签: c++ multithreading thread-safety

std::condition_variable的用法如下:

<a-entity id="player" networked="template:#avatar-template;showLocalTemplate:false;" 
            camera spawn-in-circle="radius:3;" 
            position="0 1.3 0" 
            wasd-controls 
            look-controls 
            twoway-motion="speed: 35">

            <a-entity cursor="fuse: true; fuseTimeout: 500"
                position="0 0 -1"
                geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03"
                material="color: black; shader: flat"
                      id="defaultCursor">
            </a-entity>
  </a-entity>


<script> 
  var playerEl = document.getElementById('player');    
  var cursorEl = document.getElementById('defaultCursor');      

  playerEl.removeChild(cursorEl);

  playerEl.removeAttribute('twoway-motion'); 

  playerEl.setAttribute('progressive-controls');
 </script>

我觉得有一个有趣的问题。 std::condition_variable cv; ... std::unique_lock<std::mutex> lk(m); cv.wait(lk, []{return processed;}); 可能会被推迟,可能已经被交换掉了。通过代码设计,它可能还有其他许多原因,而不一定是没有被锁定的严重错误。例如。

unique_lock

为什么不通过使std::unique_lock<std::mutex> lk(m, std::try_to_lock_t); // or std::defer_lock_t // Try to lock fails. cv.wait(lk, []{return processed;}); std::conditional_variable一起使用来强制锁定情况?然后,您将很难进入这种情况。实际上,唯一的方法就是这样做:

lock_guard

而不是// m is not already locked std::lock_gaurd<std::mutex> lk(m, std::adopt_lock); cv.wait(lk, []{return processed;}); 中可用的多种方法。 是否有技术上的理由将unique_lock上的unique_lock用于lock_guard

2 个答案:

答案 0 :(得分:5)

条件变量需要能够锁定和解锁互斥锁,lock_guard不允许这样做。 lock_guard也不允许访问大多数条件变量实现可能需要的互斥量本身。

答案 1 :(得分:1)

lock_guardunique_lock非常相似。但是,lock_guard会锁定构造,而在破坏时会解锁。使用condition_variable互斥锁需要多次锁定和解锁。

您基本上可以在任何地方使用unique_lock,但是它们比简单的lock_guard所带来的开销更大。

  

std :: condition_variable仅适用于std :: unique_lock;   此限制允许在某些平台上获得最大效率。   std :: condition_variable_any提供有效的条件变量   带有任何BasicLockable对象,例如std :: shared_lock。

取自cppreference