web-dev-qa-db-fra.com

Ai-je besoin d'un mutex pour lire?

J'ai une classe qui a un état (une énumération simple) et qui est accessible à partir de deux threads. Pour changer d'état, j'utilise un mutex (boost :: mutex). Est-il sûr de vérifier l'état (par exemple, comparer state_ == ESTABLISHED) ou dois-je également utiliser le mutex dans ce cas? En d'autres termes, ai-je besoin du mutex quand je veux juste lire une variable qui pourrait être écrite simultanément par un autre thread?

42
Tom

Ça dépend.

Le langage C++ ne dit rien sur les threads ou l'atomicité.

Mais sur la plupart des CPU modernes, la lecture d'un entier est une opération atomique, ce qui signifie que vous lirez toujours une valeur cohérente, même sans mutex.

Cependant, sans mutex, ou toute autre forme de synchronisation, le compilateur et le CPU sont libres de réorganiser les lectures et les écritures, donc tout ce qui est plus complexe, tout ce qui implique l'accès à plusieurs variables, n'est toujours pas sûr dans le cas général .

En supposant que le thread d'écriture met à jour certaines données, puis définit un indicateur entier pour informer les autres threads que des données sont disponibles, cela pourrait être réorganisé afin que l'indicateur soit défini avant la mise à jour des données. Sauf si vous utilisez un mutex ou une autre forme de barrière de mémoire.

Donc, si vous voulez un comportement correct, vous n'avez pas besoin d'un mutex en tant que tel, et ce n'est pas un problème si un autre thread écrit dans la variable pendant que vous le lisez. Ce sera atomique, sauf si vous travaillez sur un processeur très inhabituel. Mais vous avez besoin d'une barrière de mémoire quelconque pour empêcher la réorganisation dans le compilateur ou le CPU.

19
jalf

Vous avez deux fils, ils échangent des informations, oui vous avez besoin d'un mutex et vous avez probablement aussi besoin d'une attente conditionnelle.

Dans votre exemple (compare state_ == ESTABLISHED) indique que le thread # 2 attend que le thread # 1 lance une connexion/un état. Sans mutex ni conditions/événements, le thread n ° 2 doit interroger l'état en continu.

Les threads sont utilisés pour augmenter les performances (ou améliorer la réactivité), l'interrogation entraîne généralement une baisse des performances, soit en consommant beaucoup de CPU, soit en introduisant une latence due à l'intervalle d'interrogation.

9
Ernelli

en fait, il n'y a aucune raison de verrouiller l'accès à l'objet pour la lecture. vous souhaitez uniquement le verrouiller pendant l'écriture. c'est exactement ce qu'est un verrou de lecture-écriture. il ne verrouille pas l'objet tant qu'il n'y a pas d'opérations d'écriture. il améliore les performances et empêche les blocages. voir les liens suivants pour des explications plus élaborées:

wikipediaprojet de code

2
geva30

Oui. Si le thread a lit une variable pendant que le thread b y écrit, vous pouvez lire une valeur non définie. Les opérations de lecture et d'écriture ne sont pas atomiques, en particulier sur un système multiprocesseur.

2
Jeff Ober

De manière générale, vous ne le faites pas, si votre variable est déclarée avec "volatile". Et UNIQUEMENT s'il s'agit d'une seule variable - sinon vous devez faire très attention aux races possibles.

1
EFraim

L'accès à l'énumération (lecture ou écriture) doit être protégé.

Une autre chose: si la contention des threads est moindre et que les threads appartiennent au même processus, la section Critique serait meilleure que mutex.

0
aJ.