mutex avec des objects

J’essaie de comprendre comment utiliser des mutex avec des objects en c ++. J’ai le code multi-thread (sortingvial) suivant que j’utilise comme test de vitesse:

struct Rope{ int n, steps, offset; //std::mutex mut; Rope() {} Rope(int n, int steps, int offset) : n(n), steps(steps), offset(offset) {} void compute(){ double a[n]; for (int i=0; i<n; i++) a[i] = i + offset; for (int step=0; step<steps; step++) for (int i=0; i<n; i++) a[i] = sin(a[i]); } }; void runTest(){ int numRuns = 30; int n = 10000; int steps = 10000; std::vector ropes; std::vector threads; for (int i=0; i<numRuns; i++) ropes.push_back(Rope(n, steps, i)); for (auto& r : ropes) threads.push_back(std::thread(&Rope::compute, r)); for (std::thread& t : threads) t.join(); } 

Le code fonctionne correctement tel quel, et voit une accélération de ~ 4x sur ma machine à 4 cœurs. Bien entendu, je ne stocke rien dans la corde, un mutex n’est donc pas nécessaire. Si je présume maintenant que j’avais certaines données à protéger, j’aimerais associer un mutex à la corde et (par exemple) appeler std :: lock_guard dans la boucle compute (). Cependant, si je supprime le commentaire du mutex, j’obtiens un tas d’erreurs de compilation concernant “l’utilisation de la fonction supprimée” pour les opérateurs d’affectation et de copie. Qu’est-ce qui me manque dans mon objective de verrouiller un object en toute sécurité?

Le moyen le plus simple de créer une classe threadsafe consiste à append un atsortingbut mutex et à verrouiller le mutex dans les méthodes d’access.

 class cMyClass { boost::mutex myMutex; cSomeClass A; public: cSomeClass getA() { boost::mutex::scoped_lock lock( myMutex ); return A; } }; 

Le problème est que cela rend la classe non copiable. Ceci est important, en particulier si vous souhaitez stocker des objects de la classe dans un conteneur.

Je peux faire fonctionner les choses en rendant le mutex statique.

 class cMyClass { static boost::mutex myMutex; cSomeClass A; public: cSomeClass getA() { boost::mutex::scoped_lock lock( myMutex ); return A; } }; 

Cependant, cela signifie que chaque instance de la classe est bloquée lorsqu’une autre instance est en cours d’access, car elles partagent le même mutex.

Théoriquement, une classe contenant un mutex non statique peut être copiée en codant manuellement le constructeur de la copie et l’opérateur d’affectation afin de laisser le mutex de côté. Cependant, cela est difficile et fastidieux à faire correctement, en particulier pour une classe avec un grand nombre d’atsortingbuts qui changent fréquemment au cours du développement.

Si un mutex statique qui bloque l’access à toutes les instances de la classe lorsque l’une d’entre elles est bloquée n’est pas acceptable, la meilleure et la plus simple consiste à conserver les mutex en dehors de la classe. Il peut sembler malheureux d’exposer de la sorte le fonctionnement interne d’une classe, mais les alternatives sont beaucoup plus complexes et donc peu fiables. Je trouve souvent des optimisations significatives lorsque les mutex sont gérés au niveau du code accédant à la classe.

Vous manquez le fait que le mutex n’est pas copiable. Que signifierait faire une copie d’un mutex? L’endroit où acquérir et libérer le mutex est dans Rope::compute , et comme tous les threads doivent accéder au même mutex, vous devrez le définir dans runTest et le transmettre par référence ou par pointeur.