Supprimer un mutex qui est verrouillé

J’ai un programme avec plusieurs ressources qui doit être verrouillé par leur propre mutex.

Dans ce programme, il peut arriver que, bien que mutex pour la ressource A soit verrouillé, la ressource A soit supprimée dans un autre thread.

Le code suivant tente de reproduire la logique de ce que j’essaie d’accomplir:

#include  #include  #include  #include  int g_i = 0; struct Resource { std::mutex* m_mutex; }; std::map myResources; std::mutex g_i_mutex; // protects g_i void shutdown() { std::cout < myMap.size = : " << myResources.size() << std::endl; std::lock_guard lock(*myResources[1].m_mutex); ++g_i; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); delete myResources[1].m_mutex; myResources[1].m_mutex = NULL; myResources.erase(1); std::cout < myMap.size = : " << myResources.size() << std::endl; std::cout << "shutdown : " << g_i << '\n'; } void onRecognize() { std::cout < myMap.size = : " << myResources.size() << std::endl; std::lock_guard lock(*myResources[1].m_mutex); std::cout < myMap.size = : " << myResources.size() << std::endl; ++g_i; std::cout << "onRecognize : " << g_i << '\n'; } int main() { std::cout << __func__ << ": " << g_i << '\n'; Resource myStruct; myStruct.m_mutex = new std::mutex(); myResources[1] = myStruct; std::thread t1(shutdown); std::thread t2(onRecognize); t1.join(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); t2.join(); std::cout << __func__ << ": " << g_i << '\n'; } 

J’ai essayé cet extrait de code et cela fonctionne. Mais je me demande ce qui se passe avec lock_guard dans la fonction onRecognize , car le mutex est supprimé alors qu’il est verrouillé. Donc, ma question pourrait être:

La suppression d’un mutex alors qu’il est verrouillé ailleurs est-elle dangereuse?

THX

Ne détruisez pas un mutex tant qu’il est verrouillé.

Le comportement n’est pas défini si le mutex appartient à un thread ou si un thread se termine alors qu’il est propriétaire du mutex.

http://en.cppreference.com/w/cpp/thread/mutex/~mutex

Vous avez une erreur fondamentale de concurrence qui rend votre code peu fiable. Le pointeur m_mutex est modifié dans un thread et utilisé dans un autre, aucune synchronisation ne le protège.

C’est catastrophique, même si vous ne pouvez pas imaginer un moyen d’échec. Mais il est très facile d’imaginer les moyens de l’échec. Considérer:

  1. onRecognize évalue *myResources[1].m_mutex mais n’a pas encore construit la protection de locking.
  2. shutdown acquiert le verrou, détruit le mutex et revient.
  3. onRecognize tente de construire le garde-verrou sur un verrou qui n’existe plus.
  4. Boom.

Vous avez donc des problèmes plus importants que tout ce qui est spécifique à la sémantique des mutex.