C++ std::timed_mutex::try_lock_for立即失败
我第一次使用std::timed_mutex,但它的运行方式与我预期的不同。它似乎立即失败,而不是等待互斥锁。我以毫秒为单位提供锁超时(如图所示)。但是调用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
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
是一个悬空指针。它总是会立即错误地失败,还是只是偶尔会失败?我认为虚假的失败几乎只会在发生争用或信号时发生。可能是其他时候,但不是每次使用该函数。@MichaelBurrtry\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();
}