2011-06-10 4 views
16

Pourquoi est-il nécessaire de verrouiller un mutex avant d'appeler pthread_cond_wait?Exigence pthread_cond_wait et mutex

De même, est-il nécessaire de prendre un verrou (sur le même mutex) avant d'appeler pthread_cond_signal?

merci pour votre aide.

+2

Voir aussi: http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex – ninjalj

Répondre

25

Pourquoi est-il nécessaire de verrouiller un mutex avant d'appeler pthread_cond_wait?

Parce que sinon il y a une condition de course inévitable.

Un mutex protège l'état partagé. Une variable de condition est associée à un prédicat ("condition") sur l'état. L'idée de base est que vous voulez:

1) vérifier le prédicat

2) si le prédicat est faux, allez dormir jusqu'à ce qu'il devienne vrai

Dans un système concurrent, il est toujours possible pour un thread pour rendre le prédicat vrai entre (1) et (2). Pour éviter cette course, vous devez tenir un mutex avant (1) et vous devez le relâcher atomiquement pendant que vous effectuez (2).

Par exemple, pour une file d'attente, le prédicat peut être "la file d'attente n'est pas vide". Mais entre le moment où vous vérifiez pour voir si la file d'attente est non-vide et le moment où vous allez dormir, un autre thread pourrait ajouter quelque chose à la file d'attente.

Ainsi, vous devez maintenir le mutex à la fois lors de la vérification du prédicat et au moment où vous appelez pthread_cond_wait.

De même, est-il nécessaire de prendre un verrou (sur le même mutex) avant d'appeler pthread_cond_signal?

À ma connaissance, il n'y a pas de problème fondamental avec ceci; cela introduit simplement des inefficacités potentielles.

Là encore, quel que soit l'état partagé que vous modifiez (et donc que le prédicat est vrai) doit être protégé par un mutex. Donc, chaque fois que vous voulez pour signaler la condition, vous devez déjà tenir le mutex de toute façon.

Si vous libérez le mutex avant de signaler la condition, il est possible que le prédicat devienne faux entre les deux en raison de l'action d'un autre thread. Cette course ne cause pas d'échec car tout thread qui attend la condition doit vérifier de nouveau le prédicat de toute façon avant de continuer ... Mais pourquoi le mettre en difficulté?

Bottom line: Il suffit de suivre les instructions et vous n'avez même pas à penser à ces questions. :-)

+0

+1 pour une réponse détaillée. :-) Je pense que le verrouillage de la signalisation est nécessaire pour assurer la cohérence de la mémoire, car le verrouillage d'un mutex implique une barrière de mémoire. Sans cela, d'autres threads peuvent ne pas être en mesure d'observer le changement. (Bien que, je suppose, il est possible d'avoir une barrière de mémoire à la signalisation, mais il est probablement plus simple d'exiger un verrou.) –

+1

@Chris: 'pthread_cond _ *()' est requis par POSIX pour synchroniser la mémoire: http: // pubs. opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11 – ninjalj

+0

@ninjalj: Ah, très bien. Merci! :-) –

1

Les variables d'état servent à la synchronisation d'une condition que vous souhaitez modifier. Le verrouillage garantit que:

  • Le changement peut être fiable observée sur les threads en attente
  • La question en changement n'est pas en quelque sorte changé par un autre thread en même temps l'un des fils maintenant réveillées-up est l'observation

Un système de condition qui n'utilise pas de mutex serait beaucoup plus cassant. Pourquoi est-il nécessaire de verrouiller un mutex avant d'appeler pthread_cond_wait?

1

L'ensemble des variables de condition de point est de permettre aux threads d'être notifiés des changements sur les structures de données protégées par un mutex, par ex. vous pouvez être averti lorsqu'une file d'attente n'est plus vide, donc vous libérez atomiquement le mutex et attendez sur la variable de condition, et quand un nouvel élément est mis en file d'attente, vous êtes réveillé et prenez le mutex pour traiter le nouvel élément.

Contrairement aux moniteurs Java, le pthread_cond_{signal,broadcast}() n'a pas besoin de tenir le mutex. Une signalisation d'une variable de condition lorsqu'aucun thread n'attend cette variable de condition est perdue, mais cela ne devrait pas faire beaucoup de différence, car le signal pourrait également être perdu si le producteur commence à s'exécuter avant le consommateur.