89 votes

Appel de pthread_cond_signal sans verrouiller le mutex

J'ai lu quelque part que nous devrions verrouiller le mutex avant d'appeler pthread_cond_signal et déverrouiller le mutex après l'avoir appelé :

La routine pthread_cond_signal() est utilisée pour signaler (ou réveiller) un autre thread qui est en attente de la variable de condition. Elle doit être appelée après que le mutex soit verrouillé, et doit déverrouiller le mutex pour que la pour que la routine pthread_cond_wait() soit termine.

Ma question est la suivante : n'est-il pas normal d'appeler pthread_cond_signal o pthread_cond_broadcast sans verrouiller le mutex ?

158voto

caf Points 114951

Si vous ne verrouillez pas le mutex dans le codepath qui change la condition et les signaux, vous pouvez perdre des réveils. Considérez cette paire de processus :

Processus A :

pthread_mutex_lock(&mutex);
while (condition == FALSE)
    pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);

Processus B (incorrect) :

condition = TRUE;
pthread_cond_signal(&cond);

Considérons ensuite cet entrelacement possible d'instructions, où condition commence par FALSE :

Process A                             Process B

pthread_mutex_lock(&mutex);
while (condition == FALSE)

                                      condition = TRUE;
                                      pthread_cond_signal(&cond);

pthread_cond_wait(&cond, &mutex);

Le site condition est maintenant TRUE mais le processus A est bloqué en attendant la variable de condition - il a manqué le signal de réveil. Si nous modifions le processus B pour verrouiller le mutex :

Processus B (correct) :

pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

...alors ce qui précède ne peut pas se produire ; le réveil ne sera jamais manqué.

(Notez que vous peut déplacer réellement le pthread_cond_signal() lui-même après le pthread_mutex_unlock() mais cela peut entraîner un ordonnancement moins optimal des threads, et vous avez déjà nécessairement verrouillé le mutex dans ce chemin de code en raison de la modification de la condition elle-même).

5 votes

@Nemo : Oui, dans le chemin "correct" le pthread_signal_cond() peut être déplacé après le déverrouillage du mutex, bien qu'il soit probablement préférable de ne pas le faire. Il est peut-être plus correct de dire qu'au moment où l'on appelle pthread_signal_cond() vous aurez déjà eu besoin de verrouiller le mutex pour modifier la condition elle-même.

0 votes

@Nemo : Oui, le code est cassé, c'est pourquoi il est marqué comme "incorrect" - d'après mon expérience, les personnes qui posent cette question envisagent souvent de laisser le verrouillage entièrement sur le chemin de signalisation. Peut-être votre expérience est-elle différente.

0 votes

J'ai mal interprété ce que tu disais. Je pensais que tu disais que signaler la condition après avoir déverrouillé le mutex était incorrect à cause de l'entrelacement... Je réalise que j'ai mal interprété votre réponse, j'ai donc supprimé mes autres commentaires. Mes excuses.

54voto

icecrime Points 23650

Selon ce manuel :

Le site pthread_cond_broadcast() o pthread_cond_signal() fonctions peut être appelé par un thread, qu'il possède ou non le mutex. que les fils qui appellent pthread_cond_wait() o pthread_cond_timedwait() ont associé à la variable de condition pendant leurs attentes ; cependant, si un comportement d'ordonnancement prévisible est requis, alors ce mutex doit être verrouillé par le thread qui appelle pthread_cond_broadcast() o pthread_cond_signal() .

La signification de la comportement prévisible en matière de programmation La déclaration a été expliquée par Dave Butenhof (auteur de Programmation avec les threads POSIX ) sur comp.programming.threads et est disponible aquí .

7 votes

+1 pour le lien vers le mail de Dave Butenhof. Je me suis toujours posé cette question moi-même, maintenant je sais... J'ai appris quelque chose d'important aujourd'hui. Merci.

0 votes

Si un comportement d'ordonnancement prévisible est nécessaire, placez les instructions dans un thread dans l'ordre que vous voulez, ou utilisez des priorités de thread.

8voto

Quuxplusone Points 4320

Caf, dans votre exemple de code, le processus B modifie condition sans verrouiller le mutex d'abord. Si le processus B a simplement verrouillé le mutex pendant cette modification, puis a encore déverrouillé le mutex avant d'appeler pthread_cond_signal il n'y aurait pas de problème --- ai-je raison ?

Je crois intuitivement que le café position est correct : appeler pthread_cond_signal sans posséder le verrou mutex est une mauvaise idée. Mais les cafés exemple n'est pas réellement une preuve en faveur de cette position ; c'est simplement une preuve en faveur de la position beaucoup plus faible (pratiquement évidente) que c'est une mauvaise idée de modifier un état partagé protégé par un mutex à moins d'avoir verrouillé ce mutex au préalable.

Quelqu'un peut-il fournir un exemple de code dans lequel l'appel pthread_cond_signal suivi par pthread_mutex_unlock donne un comportement correct, mais l'appel à pthread_mutex_unlock suivi par pthread_cond_signal donne un comportement incorrect ?

5 votes

En fait, je pense que ma question est une duplication de celui-ci et la réponse est "C'est bon, vous pouvez totalement appelle pthread_cond_signal sans posséder le verrou mutex. Il n'y a pas de problème de correction. Mais dans les implémentations courantes, vous ne bénéficierez pas d'une optimisation intelligente au cœur de pthreads, il est donc légèrement préférable d'appeler pthread_cond_signal tout en conservant le verrou."

0 votes

J'ai fait cette observation dans le dernier paragraphe de ma réponse.

0 votes

Vous avez un bon scénario ici : stackoverflow.com/a/6419626/1284631 Notez qu'il ne prétend pas que le comportement est incorrect, il présente seulement un cas où le comportement pourrait ne pas être celui attendu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X