Ich habe mich gefragt, was passiert, wenn Sie eine unique_lock
verschieben, die eine recursive_mutex
enthält.Einen unique_lock <rekursive_mutex> in einen anderen Thread verschieben
Insbesondere war ich an diesem Code suchen:
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!
}
Die Ausgabe dieses Beispielcode hat mich sehr überrascht. Wie weiß die unique_lock
in main(), dass der Thread den Mutex freigegeben hat? Ist es echt?
Es ist nicht klar, was Sie überraschend finden. Es gibt ein einfaches boolesches Element in 'unique_lock', das' owns_lock() 'zurückgibt und das vom move-Konstruktor in einer vorhersagbaren und dokumentierten Weise verschoben wird. 'ownes_lock()' berührt den zugrunde liegenden Mutex nicht. Allerdings zeigt Ihr Programm undefiniertes Verhalten: Wenn 'unique_lock' im Worker-Thread zerstört wird, ruft es' g_mutex.unlock() 'auf, aber der Worker-Thread hält keine Sperre für' g_mutex' (was ein pre ist -Erfordernis für 'unlock()'). –
@IgorTandetnik Danke. Es ist also nicht möglich, den Besitz eines 'rekursiven_Mutex' zwischen Threads zu verschieben. Was wäre, wenn der Mutex nicht rekursiv wäre? Würde das Verschieben des 'unique_lock' den Eigentümer wirklich in den Eigentümer-Thread verschieben? –
Das Verschieben von 'unique_lock' zwischen Threads ist absolut nicht gut für Sie. Erkenne, dass "unique_lock" nichts anderes ist als ein "mutex *" - Zeiger und eine "bool owns" -Flagge - es gibt keine schwarze Magie. Der Verschiebungskonstruktor bewegt sich einfach über diesen Zeiger und diesen booleschen Wert. Der Aufruf von 'my_mutex.unlock()' an einem anderen Thread als dem, der 'my_mutex.lock()' aufgerufen hat, weist ein nicht definiertes Verhalten auf, egal ob explizit oder indirekt, indem 'unique_lock' dazu verleitet wird. Dies gilt für alle Mutex-Aromen. –