Попробуйте поймать с замками в C ++ - PullRequest
0 голосов
/ 06 сентября 2018

В Java:

Lock lock = new ReentrantLock();
try{
  lock.lock();
  someFunctionLikelyToCauseAnException();
}
catch(e){...}
finally {
  lock.unlock();
}

Мой вопрос в этом примере выше, мы знаем, что блокировка всегда будет разблокирована, потому что, наконец, всегда выполняется, но какова гарантия с C ++?

mutex m;
m.lock();
someFunctionLikelyToCauseAnException();
/// ????

Как это будет работать и почему?

Ответы [ 3 ]

0 голосов
/ 06 сентября 2018

Для этого мы используем RAII-стиль конструкция std::lock_guard. Когда вы используете

std::mutex m;
{ // start of some scope
    std::lock_guard lg(m);
    // stuff
} // end of scope

lg гарантирует, что m будет разблокирован независимо от того, по какому пути останется область видимости, поскольку она уничтожается при выходе из области видимости, а деструктор std::lock_guard s вызовет unlock

Даже если сгенерировано исключение, стек будет размотан ( разматывание стека ), и этот процесс уничтожит lg, что в свою очередь вызовет unlock, гарантируя снятие блокировки.

0 голосов
/ 10 сентября 2018

Если исключение выдается во время выполнения фрагмента кода, защищенного критическим разделом, то есть кодами между «lock ()» и «unlock ()», это означает связанный объект, над которым работает фрагмент кода больше не в действительном состоянии. При этом может быть или не быть откатом при автоматическом раскручивании стека, инициированном исключением, потому что некоторый побочный эффект мог иметь место до того, как сгенерировано исключение (сообщение было отправлено через сокет, компьютер был запущен, например). На данный момент, большая проблема здесь не в том, будет ли освобожден мьютекс (единственная гарантия использования lock_guard вместо этого). Вполне может быть, что некоторые случаи, когда мьютекс по-прежнему заблокирован, является желательным поведением и может быть явно сброшен после очистки вызывающей стороны всей путаницы.

Моя точка зрения такова: это не проблема языка. Никакая языковая функция не может гарантировать правильную обработку ошибок. Не принимайте lock_guard и RAII как серебряную пулю.

0 голосов
/ 06 сентября 2018

что такое гарантия с C ++?

Соответствующая гарантия в C ++ работает немного иначе, чем та, которую вы упоминаете в Java.Вместо наконец-то блока он полагается на уничтожение автоматических переменных , которое происходит при выходе из области видимости, когда кадр стека разматывается.Это разматывание стека происходит независимо от того, как была завершена область действия, будь то изящно или из-за исключения.

Предпочтительный подход для сценарияв отношении таких замков предполагается использовать RAII , как это реализовано, например, std::lock_guard.Он содержит объект mutex, переданный его конструктору - внутри которого он вызывает lock() метод mutex, после которого поток владеет мьютексом - и при разматывании стека вВыход из области видимости вызывается деструктором - внутри которого он вызывает метод mutex unlock(), освобождая его.

Код будет выглядеть так:

std::mutex m;
{
    std::lock_guard lock(m);
    // Everything here is mutex-protected.
}
// Here you are guaranteed the std::mutex is released.
...