我想知道当您移动包含recursive_mutex
的unique_lock
时会发生什么。将unique_lock <recursive_mutex>移动到另一个线程
具体来说,我一直在寻找这样的代码:
recursive_mutex g_mutex;
#define TRACE(msg) trace(__FUNCTION__, msg)
void trace(const char* function, const char* message)
{
cout << std::this_thread::get_id() << "\t" << function << "\t" << message << endl;
}
future<void> foo()
{
unique_lock<recursive_mutex> lock(g_mutex);
TRACE("Owns lock");
auto f = std::async(launch::async, [lock = move(lock)]{
TRACE("Entry");
TRACE(lock.owns_lock()? "Owns lock!" : "Doesn't own lock!"); // Prints Owns lock!
this_thread::sleep_for(chrono::seconds(3));
});
TRACE(lock.owns_lock()? "Owns lock!" : "Doesn't own lock!"); // Prints Doesn't own lock!
return f;
}
int main()
{
unique_lock<recursive_mutex> lock(g_mutex);
TRACE("Owns lock");
auto f = foo();
TRACE(lock.owns_lock()? "Owns lock!" : "Doesn't own lock!"); // Prints Owns lock!
f.wait();
TRACE(lock.owns_lock()? "Owns lock!" : "Doesn't own lock!"); // Prints Owns lock!
}
此示例代码的输出让我吃惊不少。 main()中的unique_lock
如何知道线程释放了互斥锁?这是真的吗?
目前尚不清楚你会发现令人惊讶的事情。 'unique_lock'中有一个简单的布尔成员,它的'owns_lock()'返回,并且通过移动构造函数以可预测和记录的方式移动。 'owns_lock()'不会触及底层互斥体。话虽如此,你的程序展现出未定义的行为:当工作线程上'unique_lock'被销毁时,它调用'g_mutex.unlock()',但工作线程不会在'g_mutex'(这是一个pre - unlock()''的必要条件)。 –
@IgorTandetnik谢谢。所以不可能在线程之间移动'recursive_mutex'的所有权?如果互斥量不是递归会怎么样?将unique_lock移动到所有者线程是否真的会移动? –
在线程之间移动'unique_lock'确实对你没有任何好处。意识到'unique_lock'只不过是一个'互斥体*'指针和一个'bool拥有'标志 - 没有黑魔法。移动构造器简单地移动该指针和布尔值。在不同于调用'my_mutex.lock()'的线程上调用'my_mutex.unlock()'会展示未定义的行为,无论是通过欺骗'unique_lock'来明确或间接完成。所有互斥口味都是如此。 –