Eu vou usar boost::mutex
a partir de boost/thread/mutex.hpp
. Existem várias maneiras de bloquear / desbloquear mutex: com scoped_lock
, unique_lock
, lock_guard
funções-membro do mutex ::lock()
e ::unlock()
e funções não-membros lock()
e unlock()
.
Eu percebi isso boost::scoped_mutex
é uma das formas mais populares de usar o mutex. Por que é preferível às funções de membro ::lock()
e ::unlock()
?
Particularmente, por que devo usar
{
boost::scoped_lock lock(mutex)
// ...
// read/output sharing memory.
// ...
}
ao invés de
mutex.lock()
// ...
// read/output sharing memory.
// ...
mutex.unlock()
é scoped_lock
melhor apenas por causa de algum ponto de vista de codificação de estilo ou é ::lock()/::unlock()
não "fio seguro o suficiente"?
Respostas:
63 para resposta № 1Por que é preferível a funções de membro :: lock () e :: unlock ()?
Pela mesma razão porque o Idioma RAII tornou-se popular em geral (esta é apenas uma das suas inúmeras instâncias): porque você pode ter certeza que você não "deixa o escopo atual sem desbloquear o mutex.
Note que isto não é apenas sobre esquecendo chamar unlock()
: uma exceção pode ocorrer enquanto o seu mutex estiver bloqueado, e sua chamada para unlock()
pode nunca ser alcançado, mesmo que você não tenha return
declaração entre a sua chamada para lock()
e sua chamada para unlock()
.
m.lock() // m is a mutex
// ...
foo(); // If this throws, your mutex won"t get unlocked
// ...
m.unlock()
Neste caso, o destruidor do seu scoped_lock
guarda será invocado durante o desenrolamento da pilha, assegurando que o mutex associado sempre é liberado.
{
boost::scoped_lock lock(m); // m is a mutex
// ...
foo(); // If this throws, your RAII wrapper will unlock the mutex
// ...
}
Além disso, em muitas situações isso irá melhorar a legibilidade do seu código, pois você não terá que adicionar uma chamada para unlock()
antes de cada return
declaração.
2 para resposta № 2
você pode usar
std::lock_guard<std::mutex> lock(mutex);
se não quiser usar a biblioteca de reforço.