std::timed_mutex::try_lock*失败了

13

在这里,try_lock*指的是try_lock()try_lock_for()try_lock_until()。根据cppreference的描述,这三个方法都可能失败而无故返回。以下摘自try_lock_for()方法的描述:

try_lock()一样,此函数允许出现虚假唤醒,即使在timeout_duration期间没有任何其他线程锁定互斥量,该函数也会返回false

我知道使用std::condition_variable时可能会发生虚假唤醒,并了解其背后的原因。但是,对于互斥量呢?

2个回答

18

根据:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3209.htm

另一方面,有强烈的理由要求程序能够容忍try_lock()失败:

  1. 正如Boehm、Adve在PLDI 08中指出的那样,《C++并发内存模型基础》,如果在不产生数据竞争的程序中强制执行顺序一致性,而不允许try_lock()失败,则需要为try_lock()-兼容的mutex类型上的lock()操作提供更强的内存排序。在某些体系结构上,这显着增加了未争用的mutex获取成本。这种成本似乎远大于禁止try_lock()失败所带来的任何好处。
  2. 它允许用户编写的try_lock()失败,例如,如果实现无法获取用于保护mutex数据结构的低级锁,则可以直接使用compare_exchange_weak编写此类操作。
  3. 它确保客户端代码在以下情况下仍然正确,例如,引入调试线程以偶尔获取锁以能够从正在检查或检查的数据结构中读取一致的值。任何从try_lock()失败中获得信息的代码都会在引入纯粹锁定并读取数据结构的另一个线程时中断。

7

来自C++14章节“30.4.1.2 Mutex types”

第16段:

即使没有其他线程持有锁,实现也可能无法获取锁。[注:这种虚假的失败通常不常见,但允许基于简单比较和交换(第29条)的有趣实现。—end note] 实现应确保在没有竞争的互斥量获取情况下,try_lock() 不会一直返回false

第19段:

即使没有虚假故障,对于失败后的状态,我们也几乎一无所知。

回答:

我知道std::condition_variable可能会发生虚假唤醒以及背后的原理。但是,互斥锁的情况如何?

std::timed_mutex有时会使用std::condition_varible进行实现,当操作系统没有直接支持时。例如GNU libstdc++:

#if _GTHREAD_USE_MUTEX_TIMEDLOCK

...

#else // !_GTHREAD_USE_MUTEX_TIMEDLOCK

  class timed_mutex
  {
    mutex       _M_mut;
    condition_variable  _M_cv;
    bool        _M_locked = false;

  public:

    template<typename _Rep, typename _Period>
      bool
      try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
      {
        unique_lock<mutex> __lk(_M_mut);
        if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
          return false;
        _M_locked = true;
        return true;
      }

    template<typename _Clock, typename _Duration>
      bool
      try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
      {
        unique_lock<mutex> __lk(_M_mut);
        if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
          return false;
        _M_locked = true;
        return true;
      }
  };

#endif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接