46 votes

pthread_cond_wait contre sémaphore

Quels sont les avantages / inconvénients d'utiliser pthread_cond_wait ou d'utiliser un sémaphore? J'attends un changement d'état comme celui-ci:

     pthread_mutex_lock(&cam->video_lock);
    while(cam->status == WAIT_DISPLAY) {
        pthread_cond_wait(&cam->video_cond, &cam->video_lock);
    }
   pthread_mutex_unlock(&cam->video_lock);
 

En utilisant un sémaphore correctement initialisé, je pense que je pourrais le faire comme ceci:

     while(cam->status == WAIT_DISPLAY) {
        sem_wait(&some_semaphore);
    }
 

Quels sont les avantages et les inconvénients de chaque méthode?

63voto

Steve Jessop Points 166970

Un sémaphore est adapté proprement à un producteur-consommateur modèle, même s'il a d'autres utilisations. La logique du programme est responsable de s'assurer que le nombre de posts pour le nombre de périodes d'attente. Si vous postez un sémaphore, et personne n'est en attente pour l'instant, alors quand ils le font attendre, ils continuent immédiatement. Si votre problème est telle qu'elle peut être expliqué en termes de nombre de la valeur d'un sémaphore, alors il devrait être facile à résoudre avec un sémaphore.

Une variable de condition est un peu plus indulgent à certains égards. Vous pouvez par exemple utiliser cond_broadcast réveiller tous les serveurs, sans que le producteur de savoir combien elles sont. Et si vous cond_signal un condvar avec personne d'attente sur elle, puis rien ne se passe. C'est bien si vous ne savez pas si il va y avoir un auditeur intéressé. C'est aussi pourquoi l'auditeur doit toujours vérifier l'état avec le mutex lieu avant l'attente - si ils ne le font pas alors qu'ils peuvent se passer d'un signal et pas de réveil jusqu'à la prochaine (qui peut-être jamais).

Si une variable de condition est adapté pour informer les parties intéressées que l'état a changé: vous pouvez acquérir le mutex, modifier l'état de signal (ou de diffusion) la condvar et de libérer le mutex. Si cela décrit votre problème, vous êtes dans condvar territoire. Si différents auditeurs sont intéressés par différents états, vous pouvez diffuser et ils vont chacun à leur tour se réveiller, à voir si ils ont trouvé à l'état qu'ils veulent, et si ce n'est attendre de nouveau.

Il est très ardu en effet de tenter ce genre de chose avec un mutex et sémaphore. Le problème vient quand vous voulez prendre le mutex, vérifiez certains de l'état, puis attente sur le sémaphore pour les changements. Sauf si vous pouvez atomiquement libérer le mutex et d'attente sur le sémaphore (qui, dans les pthreads vous ne pouvez pas vous), vous vous retrouver en attente sur le sémaphore tout en maintenant le mutex. Ce qui bloque le mutex, ce qui signifie que les autres ne peuvent pas le prendre pour faire le changement vous vous souciez. Ainsi, vous serez tenté d'ajouter un autre mutex dans une manière qui dépend de vos besoins spécifiques. Et peut-être un autre sémaphore. Le résultat est généralement un code incorrect par des conditions de course.

Les variables de Condition échapper à ce problème, car l'appel de cond_wait libère le mutex, en la libérant pour une utilisation par d'autres. Le mutex est retrouvé avant cond_wait retourne.

IIRC, il est possible de mettre en œuvre une sorte de condvar en utilisant uniquement les sémaphores, mais si le mutex vous êtes en œuvre pour aller avec le condvar est nécessaire d'avoir trylock, puis c'est une grave à la tête-scratcher, et programmer les temps d'attente sont out. Pas recommandé. Donc, ne pas supposer que tout ce que vous pouvez faire avec un condvar peut être fait avec des sémaphores. Plus bien sûr les mutex peuvent avoir agréable de comportements que les sémaphores manque, principalement priorité inversion de l'évitement.

20voto

freespace Points 9024

Les conditions sont vous permet de faire somethings les sémaphores ne sera pas.

Par exemple, supposons que vous avez un bout de code qui nécessite un mutex, appelé m. Il a cependant besoin d'attendre jusqu'à ce qu'un autre thread a fini leur tâche, de sorte qu'il attend sur un sémaphore s. Maintenant, n'importe quel thread qui doit m est bloqué, même si le thread qui a m est en attente sur s. Ces types de situations peuvent être résolues à l'aide des instructions conditionnelles. Lorsque vous attendre au conditionnel, le mutex actuellement détenu est libéré, de sorte que les autres threads peuvent acquérir le mutex. Revenons à notre exemple et supposons conditionnelle c a été utilisé au lieu de s. Notre fil maintenant acquiert m, puis conditionnelle attend sur c. Cela libère m afin que les autres threads peuvent procéder. Quand c est disponible, m est rétabli, et notre fil d'origine peut continuer gaiement le long de son chemin.

Variables conditionnelles permet également de laisser tous les threads en attente sur une variable de condition de procéder par des pthread_cond_broadcast. En outre, il vous permet également d'effectuer un temps d'attente de sorte que vous ne finissent pas attendre indéfiniment.

Bien sûr, parfois vous n'avez pas besoin de variables conditionnelles, donc, en fonction de vos exigences, l'un ou l'autre peut-être mieux.

5voto

Blaisorblade Points 3951

Le 2ème extrait de racée, ne le faites pas.

Les autres réponses ont une belle discussion des mérites; je vais juste ajouter qu' pthread_cond_broadcast est un avantage évident des variables de condition.

Au-delà de ça, je suis juste plus utilisé pour les variables de condition pour que, comme ils sont ceux que vous utilisez en Java, même, car ils vous aider à éviter les courses lors de la vérification de l'partagé drapeaux.

En effet, dans le 2e extrait de code que vous n'avez pas de verrouillage de la protection de la lecture de la cam->statut, de sorte qu'il est accessible par le biais de données de course. La plupart des plates-formes vous permettra de sortir avec que, dans cet exemple particulier, mais cela n'a pas défini de la sémantique, par POSIX et par le modèle de mémoire de la prochaine C/C++ normes.

En fait, une véritable course condition n'est possible que si un autre thread alloue une nouvelle cam structure et remplace cam; le thread en attente pourrait voir le jour à la " cam " pointeur sans voir l'initialisation de la cam->statut. En effet, le 2ème extrait est d'avoir des ennuis, dans ce cas, et en général.

http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/

0voto

Javier Points 33134

Dans votre deuxième extrait de code, vous obtenez la serrure multitude de fois, jamais le relâcher.

En général, l'état vous êtes waintin peut être complètement exprimée par un sémaphore, alors vous pouvez simplement utiliser que. Une structure de verrouillage est de plus petite taille, et il nécessite moins d'opérations atomiques à vérifier/régler/release.

Si, au contraire, l'état est complexe, et les différentes parties du code attendre à des conditions différentes de la même variable (par exemple, ici, vous voulez x<10; là, vous voulez y>x), utilisez cond_wait.

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