web-dev-qa-db-fra.com

boost scoped_lock vs simple verrouillage / déverrouillage

Je vais utiliser boost::mutex De boost/thread/mutex.hpp. Il existe plusieurs façons de verrouiller/déverrouiller mutex: avec scoped_lock, unique_lock, lock_guard, Les fonctions membres de mutex ::lock() et ::unlock() et les fonctions non membres lock() et unlock().

J'ai remarqué que boost::scoped_mutex Est l'une des façons les plus populaires d'utiliser mutex. Pourquoi est-il préférable aux fonctions membres ::lock() et ::unlock()?

En particulier, pourquoi devrais-je utiliser

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

plutôt que

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

scoped_lock est-il préférable simplement à cause d'un point de vue de codage de style ou ::lock()/::unlock() n'est-il pas "assez sûr pour les threads"?

38
Max

Pourquoi est-il préférable aux fonctions membres :: lock () et :: unlock ()?

Pour la même raison pour laquelle le idiome RAII est devenu populaire en général (ce n'est qu'une de ses innombrables instances): parce que vous pouvez être sûr de ne pas quitter la portée actuelle sans déverrouiller le mutex.

Remarquez qu'il ne s'agit pas seulement d'oublier d'appeler unlock(): une exception peut se produire lorsque votre mutex est verrouillé et votre appel à unlock() peut ne jamais être atteint, même si vous n'avez aucune instruction return entre votre appel à lock() et votre appel à unlock().

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

Dans ce cas, le destructeur de votre garde scoped_lock Sera invoqué pendant le déroulement de la pile, en s'assurant que le mutex associé toujours est libéré.

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

De plus, dans de nombreuses situations, cela améliorera la lisibilité de votre code, dans la mesure où vous n'aurez pas à ajouter d'appel à unlock() avant chaque instruction return.

67
Andy Prowl

vous pouvez utiliser

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

si vous ne voulez pas utiliser la bibliothèque boost.

3
niketan