我想知道當您移動包含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'來明確或間接完成。所有互斥口味都是如此。 –