简体   繁体   English

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

[英]std::timed_mutex::try_lock* fail spuriously

By try_lock* , I take to mean try_lock() , try_lock_for() , and try_lock_until() . 通过try_lock* ,我的意思是try_lock()try_lock_for()try_lock_until() According to cppreference , all three methods may just fail spuriously. 根据cppreference ,这三种方法可能只是虚假地失败。 Following is quoted from the description for try_lock_for() 以下内容引用了try_lock_for()的说明

As with try_lock() , this function is allowed to fail spuriously and return false even if the mutex was not locked by any other thread at some point during timeout_duration . try_lock() ,允许此函数虚假失败并返回false即使在timeout_duration期间某个时刻互斥锁未被任何其他线程锁定也是如此。

I know that spurious wakeup may happen with std::condition_variable and the rationale behind it. 我知道std::condition_variable及其背后的基本原理可能会发生虚假的唤醒。 But, what is the case with a mutex? 但是,互斥量是什么情况?

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

On the other hand, there are strong reasons to require that programs be written to tolerate spurious try_lock() failures: 另一方面,有充分的理由要求编写程序以容忍虚假的try_lock()失败:

  1. As pointed out in Boehm, Adve, "Foundations of the C++ Concurrency Memory Model", PLDI 08, enforcing sequential consistency for data-race-free programs without spurious try_lock() failures requires significantly stronger memory ordering for lock() operations on try_lock()-compatible mutex types. 正如Boehm,Adve,“C ++并发内存模型的基础”,PLDI 08所指出的那样,在没有虚假try_lock()失败的情况下强制执行无数据争用程序的顺序一致性需要对try_lock上的lock()操作进行更强大的内存排序( ) - 兼容的互斥类型。 On some architectures that significantly increases the cost of uncontended mutex acquisitions. 在一些架构上,显着增加了无争用互斥收购的成本。 This cost appears to greatly outweigh any benefit from prohibiting spurious try_lock() failures. 这个成本似乎大大超过了禁止虚假try_lock()失败的任何好处。
  2. It allows a user-written try_lock() to fail if, for example, the implementation fails to acquire a low-level lock used to protect the mutex data structure. 例如,如果实现无法获取用于保护互斥锁数据结构的低级锁定,则它允许用户编写的try_lock()失败。 Or it allows such an operation to be written directly in terms of compare_exchange_weak. 或者它允许这样的操作直接用compare_exchange_weak编写。
  3. It ensures that client code remains correct when, for example, a debugging thread is introduced that occasionally acquires locks in order to be able to read consistent values from a data structure being checked or examined. 例如,当引入调试线程时,它确保客户端代码保持正确,该调试线程偶尔获取锁,以便能够从正在检查或检查的数据结构中读取一致值。 Any code that obtains information from try_lock() failure would break with the introduction of another thread that purely locks and reads the data structure. 从try_lock()失败中获取信息的任何代码都会因为引入另一个纯粹锁定和读取数据结构的线程而中断。

From C++14 chapter "30.4.1.2 Mutex types" 来自C ++ 14章“30.4.1.2互斥体类型”

paragraph 16: 第16段:

An implementation may fail to obtain the lock even if it is not held by any other thread. 即使没有任何其他线程持有,实现也可能无法获得锁定。 [Note: This spurious failure is normally uncommon, but allows interesting implementations based on a simple compare and exchange (Clause 29). [注意:这种虚假失败通常不常见,但允许基于简单比较和交换的有趣实现(第29条)。 —end note] An implementation should ensure that try_lock() does not consistently return false in the absence of contending mutex acquisitions. -end note]实现应确保try_lock()在没有竞争互斥获取的情况下不会始终返回false

and paragraph 19: 和第19段:

little would be known about the state after a failure, even in the absence of spurious failures 即使在没有虚假失败的情况下,在失败后对状态也知之甚少

And in answer to 并回答

I know that spurious wakeup may happen with std::condition_variable and the rationale behind it. 我知道std :: condition_variable及其背后的基本原理可能会发生虚假的唤醒。 But, what is the case with a mutex? 但是,互斥量是什么情况?

std::timed_mutex sometimes is implemented using std::condition_varible when there is no direct support in the OS. std::timed_mutex有时是在操作系统中没有直接支持时使用std::condition_varible实现的。 As in GNU libstdc++: 与在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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM