web-dev-qa-db-fra.com

Équivalent C ++ 11 pour booster shared_mutex

Existe-t-il un équivalent C++ 11 pour le boost::shared_mutex. Ou une autre solution pour gérer une situation de plusieurs lecteurs/écrivains uniques en C++ 11?

54
Haatschii

J'ai essayé mais je n'ai pas réussi à obtenir shared_mutex en C++ 11. Il a été proposé pour une future norme. La proposition est ici .

Edit : Une version révisée (N3659) a été acceptée pour C++ 14.

Voici une implémentation:

http://howardhinnant.github.io/shared_mutex

http://howardhinnant.github.io/shared_mutex.cpp

69
Howard Hinnant

Simple ... Il n'y en a pas. Il n'y a pas d'implémentation C++ standard d'un lecteurs-écrivains verrou.

Mais, vous avez quelques options ici.

  1. Vous êtes laissé à vos propres appareils pour verrouiller votre propre lecteur-écrivain.
  2. Utilisez une implémentation spécifique à la plate-forme telle que Win32's , POSIX's , ou Boost's comme vous le mentionnez.
  3. N'en utilisez pas du tout - utilisez un mutex qui existe déjà en C++ 11.

Aller avec # 1 et implémenter le vôtre est une entreprise effrayante et il est possible de deviner votre code avec les conditions de course si vous ne le faites pas correctement. Il y a implémentation de référence qui peut rendre le travail un peu plus facile.

Si vous voulez du code indépendant de la plate-forme ou si vous ne voulez pas inclure de bibliothèques supplémentaires dans votre code pour quelque chose d'aussi simple qu'un verrou de lecture/écriture, vous pouvez jeter # 2 par la fenêtre.

Et, # 3 a quelques mises en garde que la plupart des gens ne réalisent pas: l'utilisation d'un verrou de lecture/écriture est souvent moins performante et a un code plus difficile à comprendre qu'une implémentation équivalente utilisant un simple mutex. Cela est dû à la tenue de livres supplémentaire qui doit se dérouler dans les coulisses d'une implémentation de verrouillage lecteurs-écrivains.


Je ne peux que vous présenter vos options, c'est à vous de peser les coûts et les avantages de chacun et de choisir celui qui fonctionne le mieux.


Edit: C++ 17 a maintenant un shared_mutex type pour les situations où les avantages d'avoir plusieurs lecteurs simultanés l'emportent sur le coût de performance du shared_mutex lui-même.

18
Sean Cline

Non, il n'y a pas d'équivalent pour boost::shared_mutex en C++ 11.

Les verrous en lecture/écriture sont pris en charge dans C++ 14 ou version ultérieure, cependant:

La différence est que std::shared_timed_mutex ajoute des opérations de synchronisation supplémentaires. Il implémente le concept SharedTimedMutex , qui est une extension du plus simple concept TimedMutex implémenté par std::shared_mutex.


Gardez à l'esprit que l'acquisition d'un verrou pour un mutex de lecture/écriture est plus coûteuse que l'acquisition d'un normal std::mutex . Par conséquent, un mutex lecture/écriture n'améliorera pas les performances si vous avez des opérations de lecture fréquentes mais courtes. Il convient mieux aux scénarios où les opérations de lecture sont fréquentes et coûteuses. Pour citer poste d'Anthony Williams :

Le coût du verrouillage d'un shared_mutex est plus élevé que celui du verrouillage d'un std :: mutex ordinaire, même pour les threads de lecture. C'est une partie nécessaire de la fonctionnalité --- il y a plus d'états possibles d'un shared_mutex qu'un mutex, et le code doit les gérer correctement. Ce coût provient à la fois de la taille de l'objet (qui, dans votre implémentation et dans mon implémentation POSIX, comprend à la fois un mutex simple et une variable de condition), et dans les performances des opérations de verrouillage et de déverrouillage.

En outre, le shared_mutex est un point de discorde, et donc pas évolutif. Le verrouillage d'un shared_mutex modifie nécessairement l'état du mutex, même pour un verrou en lecture. Par conséquent, la ligne de cache contenant l'état shared_mutex doit être transférée vers le processeur qui effectue une opération de verrouillage ou de déverrouillage.

Si vous avez beaucoup de threads effectuant des opérations de lecture courtes et fréquentes, alors sur un système multiprocesseur, cela peut entraîner beaucoup de ping-pong de cache, ce qui aura un impact considérable sur les performances du système. Dans ce cas, vous pouvez également adopter la conception plus simple de l'utilisation d'un simple mutex, car les lecteurs sont essentiellement sérialisés de toute façon.

Si les lectures ne sont pas fréquentes, il n'y a pas de conflit, vous n'avez donc pas à vous soucier des lecteurs simultanés, et un simple mutex suffira de toute façon pour ce scénario.

Si les opérations de lecture prennent du temps, la conséquence de cette contention est moins visible, car elle est éclipsée par le temps passé à maintenir le verrou de lecture. Cependant, effectuer des opérations longues en tenant un verrou est une odeur de conception.

Dans la grande majorité des cas, je pense qu'il existe de meilleures alternatives à un shared_mutex. Il peut s'agir d'un simple mutex, du support atomique de shared_ptr, de l'utilisation d'un conteneur simultané soigneusement construit, ou de quelque chose d'autre, selon le contexte.

6
Philipp Claßen