我想知道当你移动一个unique_lock
的{{1}}时会发生什么。
具体来说,我正在看这段代码:
recursive_mutex
此示例代码的输出让我感到非常惊讶。 main()中的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!
}
如何知道线程释放了互斥锁?这是真的吗?
答案 0 :(得分:4)
您似乎将某些魔法属性归因于unique_lock
。它没有任何东西,它是一个非常简单的类。它有两个数据成员Mutex* pm
和bool owns
(仅为展示显示成员名称)。 lock()
只是pm->lock(); owns = true;
,unlock
执行pm->unlock(); owns = false;
。析构函数是if (owns) unlock();
。将构造函数副本移动到两个成员上,并相应地将它们设置为原始文件nullptr
和false
。 owns_lock()
会返回owns
成员的值。
所有线程同步魔法都在互斥锁本身及其lock()
和unlock()
方法中。 unique_lock
只是它周围的薄包装。
现在,作为先决条件,调用mutex.unlock()
的线程必须持有互斥锁(意味着该线程先前已在其上调用lock()
),否则程序将显示未定义的行为。无论您是明确地调用unlock
,还是像unique_lock
那样使用某个帮助来为您调用它,都是如此。
鉴于这一切,将unique_lock
实例移动到另一个线程仅仅是此后不久触发未定义行为的一个方法;没有好处。