std :: timed_mutex :: try_lock*虚假失败

Lin*_*gxi 11 c++ multithreading mutex thread-synchronization c++11

通过try_lock*,我采取的意思是try_lock(),try_lock_for()try_lock_until().根据cppreference,这三种方法可能只是虚假地失败.以下是从描述中引用的try_lock_for()

与此同时try_lock(),false即使互斥锁在某个时刻未被任何其他线程锁定,也允许此函数虚假失败并返回timeout_duration.

我知道可能会发生虚假的唤醒std::condition_variable及其背后的基本原理.但是,互斥量是什么情况?

And*_*ers 16

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

另一方面,有充分的理由要求编写程序以容忍虚假的try_lock()失败:

  1. 正如Boehm,Adve,"C++并发内存模型的基础",PLDI 08所指出的那样,在没有虚假try_lock()失败的情况下强制执行无数据争用程序的顺序一致性需要对try_lock上的lock()操作进行更强大的内存排序( ) - 兼容的互斥类型.在一些架构上,显着增加了无争用互斥收购的成本.这个成本似乎大大超过了禁止虚假try_lock()失败的任何好处.
  2. 例如,如果实现无法获取用于保护互斥锁数据结构的低级锁定,则它允许用户编写的try_lock()失败.或者它允许这样的操作直接用compare_exchange_weak编写.
  3. 例如,当引入调试线程时,它确保客户端代码保持正确,该调试线程偶尔获取锁,以便能够从正在检查或检查的数据结构中读取一致值.从try_lock()失败中获取信息的任何代码都会因为引入另一个纯粹锁定和读取数据结构的线程而中断.


Vic*_*nko 6

来自C++ 14章"30.4.1.2互斥体类型"

第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
Run Code Online (Sandbox Code Playgroud)