C++ std::timed_mutex::try_lock_for立即失败

C++ std::timed_mutex::try_lock_for立即失败,c++,c++11,mutex,C++,C++11,Mutex,我第一次使用std::timed_mutex,但它的运行方式与我预期的不同。它似乎立即失败,而不是等待互斥锁。我以毫秒为单位提供锁超时(如图所示)。但是调用try\u lock\u for()立即失败 下面是处理锁定和解锁互斥锁的类: const unsigned int DEFAULT_MUTEX_WAIT_TIME_MS = 5 * 60 * 1000; class ScopedTimedMutexLock { public: ScopedTimedMutexLo

我第一次使用std::timed_mutex,但它的运行方式与我预期的不同。它似乎立即失败,而不是等待互斥锁。我以毫秒为单位提供锁超时(如图所示)。但是调用
try\u lock\u for()
立即失败

下面是处理锁定和解锁互斥锁的类:

  const unsigned int DEFAULT_MUTEX_WAIT_TIME_MS = 5 * 60 * 1000;

  class ScopedTimedMutexLock
  {
  public:
     ScopedTimedMutexLock(std::timed_mutex* sourceMutex, unsigned int numWaitMilliseconds=DEFAULT_MUTEX_WAIT_TIME_MS)
        m_mutex(sourceMutex)
     {
        if( !m_mutex->try_lock_for( std::chrono::milliseconds(numWaitMilliseconds) ) )
        {
           std::string message = "Timeout attempting to acquire mutex lock for ";
           message += Conversion::toString(numWaitMilliseconds);
           message += "ms";
           throw MutexException(message);
        }
     }
     ~ScopedTimedMutexLock()
     {
        m_mutex->unlock();
     }
  private:
     std::timed_mutex* m_mutex;
  };
这就是它被使用的地方:

  void  CommandService::Process( RequestType& request )
  {
     unsigned long callTime =
        std::chrono::duration_cast< std::chrono::milliseconds >(
           std::chrono::system_clock::now().time_since_epoch()
        ).count();

     try
     {
        ScopedTimedMutexLock lock( m_classMutex, request.getLockWaitTimeMs(DEFAULT_MUTEX_WAIT_TIME_MS) );
        // ... command processing code goes here
     }
     catch( MutexException& mutexException )
     {
        unsigned long catchTime =
           std::chrono::duration_cast< std::chrono::milliseconds >(
              std::chrono::system_clock::now().time_since_epoch()
           ).count();
        cout << "The following error occured while attempting to process command"
             << "\n   call  time: " << callTime
             << "\n   catch time: " << catchTime;
        cout << mutexException.description();
     }
  }
知道哪里出了问题吗?转换为
std::chrono::millides
正确吗?如何使
try\u lock\u for()
等待锁定


其他信息:调用
try\u lock\u for()
并不总是立即失败。很多时候,调用获得了锁,一切都按预期进行。我看到的失败是断断续续的。有关失败原因的详细信息,请参见下面的答案。

在的
try\u lock\u for()
说明中提到了问题的根本原因。在描述的末尾,它说:

与try_lock()一样,此函数允许错误地失败,并且 返回false,即使互斥锁未被任何其他线程锁定 超时期间的某个点

我天真地假设只有两种可能的结果:(1)函数在时间段内获得锁,或者(2)函数在等待时间过后失败。但还有另一种可能性,(3)该功能在相对较短的时间后由于没有指定的原因而失败。TL;医生,我的错

我通过重写
ScopedTimedMutexLock
构造函数,在
try_lock()
上循环,直到获得锁或超过等待时间限制,从而解决了这个问题

 ScopedTimedMutexLock(std::timed_mutex* sourceMutex, unsigned int numWaitMilliseconds=DEFAULT_MUTEX_WAIT_TIME_MS)
    m_mutex(sourceMutex)
 {
    const unsigned SLEEP_TIME_MS = 5;
    bool isLocked = false;
    unsigned long startMS = now();
    while( now() - startMS < numWaitMilliseconds && !isLocked )
    {
       isLocked = m_sourceMutex->try_lock();
       if( !isLocked )
       {
          std::this_thread::sleep_for(
              std::chrono::milliseconds(SLEEP_TIME_MS));
       }
    }
    if( !isLocked )
    {
       std::string message = "Timeout attempting to acquire mutex lock for ";
       message += Conversion::toString(numWaitMilliseconds);
       message += "ms";
       throw MutexException(message);
    }
 }

您提供的链接指的是
std::unique\u lock::try\u lock\u for
,但您使用的是
std::timed\u mutex::try\u lock\u for
。顺便说一句,还有
std::to_string
,对于简单的内置类型,不需要有自己的
Conversion::to string
。也许您可以提供一个MVCE(通过清除任何不必要的代码并提供一个工作的
main()
)?是的,当您唯一的声明是尽早尝试锁定中止时,您的代码看起来非常复杂。您有异常、指针、自定义类,所有这些都是噪声:为了确定您的声明是否正确,您要求我们首先调试或验证一堆代码。当你问“为什么这段代码不能工作”时,这些都是必需的,上面的内容既不简单也不完整。我猜可能是代码中未显示的未定义行为。例如,
*m_classMutex
已由进行调用的线程拥有;或者
m_classMutex
是一个悬空指针。它总是会立即错误地失败,还是只是偶尔会失败?我认为虚假的失败几乎只会在发生争用或信号时发生。可能是其他时候,但不是每次使用该函数。@MichaelBurr
try\u lock\u for()
都会间歇性失败。这听起来更像我所期望的。然而,您看到的虚假失败似乎是一个实现错误。C++11/14标准对
timed_mutex::try_lock_for()
(重点添加):“只有当函数获得互斥对象的所有权时,它才会在rel_time指定的超时内返回”。所以函数不应该在超时之前结束,除非它已经获得了锁。(但是,即使锁可用,它也可能无法获取锁-但在这种情况下,它仍然无法返回,直到时间到期)。您使用的工具链是什么?arm-none-linux-gnueabi-g++--版本显示
arm-none-linux-gnueabi-g++(crosstool NG hg+default-9838aecd6340-tc0003)4.8.2 20131014(预发布)
使用gcc 4.8.1我看到了错误。使用GCC6.3.0,我看不到它。
 ScopedTimedMutexLock(std::timed_mutex* sourceMutex, unsigned int numWaitMilliseconds=DEFAULT_MUTEX_WAIT_TIME_MS)
    m_mutex(sourceMutex)
 {
    const unsigned SLEEP_TIME_MS = 5;
    bool isLocked = false;
    unsigned long startMS = now();
    while( now() - startMS < numWaitMilliseconds && !isLocked )
    {
       isLocked = m_sourceMutex->try_lock();
       if( !isLocked )
       {
          std::this_thread::sleep_for(
              std::chrono::milliseconds(SLEEP_TIME_MS));
       }
    }
    if( !isLocked )
    {
       std::string message = "Timeout attempting to acquire mutex lock for ";
       message += Conversion::toString(numWaitMilliseconds);
       message += "ms";
       throw MutexException(message);
    }
 }
  private:
     unsigned long now() {
        return std::chrono::duration_cast< std::chrono::milliseconds >(
            std::chrono::system_clock::now().time_since_epoch() ).count();
     }