Question

Quels sont les avantages / inconvénients de l'utilisation pthread_cond_wait ou de l'utilisation d'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 pouvoir 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?

Était-ce utile?

La solution

Un sémaphore convient parfaitement à un modèle producteur-consommateur, bien qu'il ait d'autres utilisations. La logique de votre programme est chargée de veiller à ce que le nombre de postes correspondant au nombre d’attentes soit correct. Si vous publiez un sémaphore et que personne ne l’attend pour le moment, il attend immédiatement après. Si votre problème est tel qu'il peut être expliqué en termes de la valeur de comptage d'un sémaphore, il devrait être facile à résoudre avec un sémaphore.

Une variable de condition est un peu plus clémente à certains égards. Vous pouvez par exemple utiliser cond_broadcast pour réveiller tous les serveurs, sans que le producteur sache combien il y en a. Et si vous signalez un condvar sans attendre personne, rien ne se passe. C'est bien si vous ne savez pas s'il y aura un auditeur intéressé. C’est aussi pourquoi l’auditeur doit toujours vérifier l’état avec le mutex tenu avant d’attendre - s’ils ne le font pas, ils peuvent rater un signal et ne pas se réveiller avant le prochain (qui pourrait ne jamais être).

Ainsi, une variable de condition convient pour notifier aux parties intéressées que l'état a changé: vous acquérez le mutex, changez l'état, signalez (ou diffusez) le condvar et libérez le mutex. Si cela décrit votre problème, vous êtes en territoire favorable. Si différents auditeurs sont intéressés par différents états, vous pouvez simplement les diffuser et ils se réveilleront à leur tour, détermineront s'ils ont trouvé l'état qu'ils souhaitent et, sinon, ils n'attendront plus.

C’est vraiment très maladroit d’essayer ce genre de chose avec un mutex et un sémaphore. Le problème survient lorsque vous voulez utiliser le mutex, vérifier un état, puis attendre que le sémaphore soit modifié. À moins que vous ne puissiez libérer le mutex de manière atomique et attendre le sémaphore (ce que vous ne pouvez pas lire dans les lectures), vous finissez par attendre le sémaphore pendant que vous tenez le mutex. Cela bloque le mutex, ce qui signifie que les autres ne peuvent pas le prendre pour effectuer le changement qui vous tient à cœur. Vous serez donc tenté d’ajouter un autre mutex d’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 avec des conditions de concurrence néfastes.

Les variables de condition échappent à ce problème, car l'appel de cond_wait libère automatiquement le mutex, le libérant ainsi pour une utilisation par d'autres. Le mutex est repris avant le retour de cond_wait.

IIRC il est possible d'implémenter une sorte de condvar en utilisant seulement des sémaphores, mais si le mutex que vous implémentez pour aller avec le condvar doit avoir trylock, alors c'est un casse-tête sérieux, et les attentes chronométrées sont terminées. Non recommandé. Donc, ne supposez pas que tout ce que vous pouvez faire avec un condvar peut être fait avec des sémaphores. De plus, bien sûr, les mutex peuvent avoir de bons comportements qui manquent aux sémaphores, principalement l’évitement des inversions de priorité.

Autres conseils

Les conditions vous permettent de faire certaines choses que les sémaphores ne feront pas.

Par exemple, supposons que vous ayez du code nécessitant un mutex, appelé m. Cependant, il doit attendre qu'un autre thread ait terminé sa tâche, il attend donc un sémaphore appelé s. Désormais, tout thread ayant besoin de c est bloqué, même si le thread pthread_cond_broadcast attend <=>. Ce type de situation peut être résolu à l'aide de conditions. Lorsque vous attendez sur une condition, le mutex actuellement maintenu est libéré, afin que d'autres threads puissent acquérir le mutex. Revenons donc à notre exemple et supposons que le conditionnel <=> ait été utilisé à la place de <=>. Notre fil acquiert maintenant <=>, puis les attentes conditionnelles sur <=>. Ceci libère <=> afin que les autres threads puissent continuer. Lorsque <=> devient disponible, <=> est à nouveau acquis et notre thread initial peut continuer joyeusement le long de son chemin.

Les variables conditionnelles vous permettent également de laisser tous les threads en attente d’une variable conditionnelle passer par <=>. En outre, cela vous permet également d’effectuer une attente chronométrée afin de ne pas attendre en permanence.

Bien sûr, vous n’avez parfois pas besoin de variables conditionnelles. Par conséquent, en fonction de vos besoins, l’une ou l’autre peut être meilleure.

Le deuxième extrait est racé, ne faites pas ça.

Les autres réponses traitent bien du mérite relatif; J'ajouterai simplement que pthread_cond_broadcast est un avantage évident des variables de condition.

Au-delà de cela, je suis plus habitué à conditionner les variables pour cela, car elles sont ce que vous utilisez en Java, même parce qu'elles vous aident à éviter les courses lors de la vérification des indicateurs partagés.

En effet, dans le deuxième extrait, vous ne disposez d'aucun verrou protégeant la lecture de cam - > status, il est donc accessible via une course de données. La plupart des plateformes vous laisseront vous en tirer dans cet exemple particulier, mais cela a une sémantique non définie, par POSIX et par le modèle de mémoire des prochains standards C / C ++.

En fait, une véritable situation de concurrence critique est possible si un autre thread alloue une nouvelle structure de came et remplace la caméra. le thread en attente peut voir la mise à jour du pointeur 'cam' sans voir l'initialisation de cam - > status. En effet, le deuxième extrait demande des ennuis, dans ce cas et en général.

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

Dans votre deuxième extrait, vous obtenez le verrou plusieurs fois, sans le relâcher.

En général, l'état dans lequel vous vous trouvez peut être complètement exprimé par un sémaphore. Vous pouvez alors l'utiliser. Une structure de verrou est de taille plus petite et nécessite moins d'opérations atomiques pour vérifier / définir / libérer.

Sinon, si l'état est complexe et que différentes parties du code attendent dans différentes conditions de la même variable (par exemple, ici vous voulez x < 10; là vous voulez y > x) , utilisez cond_wait.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top