Перемещение уникального замка & lt; recursive_mutex & gt; в другой поток

Мне было интересно, что происходит, когда вы двигаете 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!
}

Вывод этого примера кода меня очень удивил. Как работает unique_lock в main () знаете, что поток выпустил мьютекс? Это реально?

3

Решение

Вы, кажется, приписываете некоторые магические свойства 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 передача в другой поток — просто рецепт для запуска неопределенного поведения вскоре после этого; нет никаких преимуществ

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]