#c #locking #mutex
#c #блокировка #мьютекс
Вопрос:
У меня есть if-ветвь, например:
MLOCK.lock();
if (CPRIMES[snode->cid] == snode) {
CPRIMES.erase(snode->cid);
log("[remove_storage_node] Node " kv_addr " dropped as primary", VB);
MLOCK.unlock();
elect_new_primary(snode->cid);
}
MLOCK.unlock();
Я хочу убедиться, что блокировка разблокирована перед вызовом elect_new_primary
, а также в конце блока кода. Это плохая практика? Какой лучший способ обеспечить разблокировку блокировки таким образом?
Комментарии:
1. Вы пробовали, что происходит? Я бы рекомендовал
std::lock_guard
вместо этого использовать s.
Ответ №1:
Предполагается, что этот ответ MLOCK
относится к стандартному объекту мьютекса std::mutex
.
От std::mutex::unlock
:
Мьютекс должен быть заблокирован текущим потоком выполнения, в противном случае поведение не определено.
Следовательно, ваш код имеет неопределенное поведение при попытке разблокировать разблокированный мьютекс.
Такого рода проблемы лучше всего решать с помощью стандартного класса std::unique_lock
. Этот класс будет управлять блокировкой и, когда его собственное время жизни закончится, он обязательно разблокирует мьютекс, если он все еще заблокирован.
Например :
#include <mutex>
std::mutex m;
void foo(bool b)
{
// Lock `m` and take ownership of that lock
std::unique_lock<std::mutex> lock{m};
if(b) {
// Unlocks `m`
lock.unlock();
}
} // `m` will be unlocked if it wasn't unlocked previously
Вы должны очень редко прибегать к прямому вызову lock
unlock
функций-членов or mutex
объекта.
Ответ №2:
Из cppreference:
std::mutex::unlock Разблокирует мьютекс. Мьютекс должен быть заблокирован текущим потоком выполнения, в противном случае поведение не определено.
Так что нет, вы не должны этого делать. Вместо этого вы должны отслеживать, заблокировали ли вы его, используя std::lock_guard
или каким-либо другим способом.