Увеличить scoped_lock против простой блокировки/разблокировки

Я собираюсь использовать boost::mutex из boost/thread/mutex.hpp. Существует несколько способов блокировки/разблокировки мьютекса: с помощью scoped_lock, unique_lock, lock_guard, функций-членов mutex ::lock() и ::unlock() и несимвольных функций lock() и unlock().

Я заметил, что boost::scoped_mutex является одним из самых популярных способов использования мьютекса. Почему предпочтительнее функции-члены ::lock() и ::unlock()?

В частности, почему я должен использовать

{
  boost::scoped_lock lock(mutex)
  // ...
  // read/output sharing memory.
  // ...
}

а не

mutex.lock()
// ...
// read/output sharing memory.
// ...
mutex.unlock()

является scoped_lock лучше только из-за некоторой точки кодирования стиля или является ::lock()/::unlock() не "потоком достаточно безопасным"?

Ответ 1

Почему это предпочтительнее для функций-членов: lock() и:: unlock()?

По той же причине, почему RAII-идиома стала популярной вообще (это всего лишь один из ее бесчисленных экземпляров): потому что вы можете быть уверены, что не оставите текущей области без разблокировки мьютекса.

Обратите внимание, что это не просто забыть вызвать unlock(): может произойти исключение, если ваш мьютекс заблокирован, а ваш вызов unlock() никогда не будет достигнут, даже если у вас нет return между вызовом lock() и вашим вызовом unlock().

m.lock() // m is a mutex
// ...
foo(); // If this throws, your mutex won't get unlocked
// ...
m.unlock()

В этом случае деструктор вашего защитника scoped_lock будет вызван во время разматывания стека, убедившись, что связанный мьютекс всегда освобождается.

{
    boost::scoped_lock lock(m); // m is a mutex
    // ...
    foo(); // If this throws, your RAII wrapper will unlock the mutex
    // ...
}

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

Ответ 2

вы можете использовать

std::lock_guard<std::mutex> lock(mutex);

если вы не хотите использовать библиотеку boost.