Utilise une serrure a de meilleures performances que d'utiliser un sémaphore local (application unique)? P>
J'ai lu ce blog de MSDN: Solution de consommateur producteur sur msdn p>
Et je n'ai pas aimé leur solution au problème car il y a toujours 20 éléments laissés dans la file d'attente. P>
Donc, à la place, j'ai pensé à utiliser un «sémaphore» qui sera disponible uniquement dans mon application (je ne le nommerai tout simplement pas dans le constructeur), mais je ne sais pas comment cela affectera la performance de l'application. < / p>
Quelqu'un a-t-il une idée si cela affectera la performance? Quelles sont les autres considérations pour utiliser un verrou et non «sémaphore»? P>
5 Réponses :
verrouillage (obj) est identique à moniteur.enter (obj); Un verrou est basicaly un sémaphore unaire. Si vous avez un certain nombre d'instances de la même ressource (n), vous utilisez un sémaphore avec la valeur d'initialisation N. Un verrouillage est principalement utilisé pour assurer qu'une section de code n'est pas exécutée par deux threads en même temps. P>
Donc, une serrure peut être mise en œuvre à l'aide d'un sémaphore avec une valeur d'initialisation de 1. Je suppose que mon moniteur.enter est plus performant ici, mais je n'ai aucune information réelle à ce sujet. Un test sera utile ici. Voici un SO Thread qui fait face à la performance. P>
Pour votre problème, une file d'attente de blocage serait la solution. (Consumer producteur) Je suggère Ce très bon alors fil. p>
Voici une autre bonne source d'informations sur structures de données parallèles réutilisables a>. p>
Merci pour la réponse mais ça ne répond pas vraiment à ma question :)
J'ai ajouté un lien vers un autre sifflement qui gère la performance. Cela vous aide-t-il?
Remarque: un sémaphore (au niveau du système d'exploitation) utilise la serrure matérielle beaucoup plus rapide, de sorte que la mise en oeuvre d'un verrou à l'aide d'un sémaphore semble un peu contrapoductive.
La serrure est en fait différente de la sémaphore, compte tenu de la réentrancement: la serrure est réentrante, tandis que le sémaphore n'est pas. Le sémaphore peut toutefois être libéré dans d'autres fils.
La solution dans l'article MSDN a un bogue où vous manquerez un événement si Setevent est appelé deux fois par le producteur de succession rapide, tandis que le consommateur traite le dernier article qu'elle extrait de la file d'attente. P>
Regardez cet article pour une implémentation différente à l'aide du moniteur à la place: P>
http://wekempf.spaces.live.com/blog /cns!D18C3EC06EA971CFF!672.Entry P>
Merci pour la réponse, mais votre message a un bogue différent .. La vérification du consommateur qui vérifie si la taille de la file d'attente n'est pas égale à zéro est problématique. Exemple: la file d'attente contient un produit. Deux clients font la vérification simultanément et entrez la boucle tandis que, on verrouille le moniteur et l'autre attend. Le premier consomme le produit (il n'y a donc plus de produits!), puis quitte le moniteur. Maintenant, le second pénètre dans le moniteur et essayez de déroger une file d'attente vide. Erreur fatale.
En fait, lorsque le second consommateur se réveille dans la boucle interne tandis que la boucle et réacquierez la serrure, il continuera de boucler et de vérifier si la file d'attente est vide avant de décider de continuer et de déroger de la file d'attente afin de ne pas obtenir l'erreur. Vous venez de mentionner. Toutefois, comme l'auteur a mentionné que ce n'est qu'une implémentation partielle et que cela ne fait rien avec l'élément de déséquilibre.
En général: Si votre thread de consommateur parvient à traiter chaque élément de données suffisamment rapidement, la transition en mode du noyau entraînera une (éventuellement significatif) de frais généraux. Dans ce cas, une enveloppe en mode utilisateur qui tourne pendant un moment avant d'attendre sur le sémaphore évitera une partie de cette surcharge. P>
Un moniteur (avec exclusion mutuelle + variable de condition) peut ou non mettre en œuvre de la filature. L'implémentation de l'article de MSDN n'a pas fait, donc dans ce cas, il n'y a pas de différence réelle dans la performance. Quoi qu'il en soit, vous allez toujours avoir à verrouiller afin de déshabiller des objets, sauf si vous utilisez une file d'attente sans verrouillage. P>
spécifications strong>: p> J'ai essayé d'exécuter 2, 4 et 6 résultats strong>
Pour chaque cas, Veuillez noter em>, je ne prétends pas qu'il est plus rapide sur un nombre infini d'autres configurations. P> p> verrouillage code> fonctionne presque deux fois plus vite que
semaphoreslim (1) code >.
2.1.5 CODE> LI>
2.5 GHz code> li>
ul>
Tâche code> s en parallèle, chacun d'entre eux faisant 1M de opérations d'accès à une serrure, faire une opération triviale et la libérant. Le code ressemble comme suit: p>
verrouillage code> a couru presque deux fois aussi vite que
semaphoreslim (1) code> (par exemple,
205ms code> vs
390ms code> 390ms code>
6 code> Tâches parallèles). P>
Il faut plutôt comparer le verrouillage vs spinlock. Pour plus d'informations, recherchez "PerformanceCharacteristicsOsSyncPrimitives.pdf" ici: Microsoft. com / fr-nous / télécharger / détails.aspx? id = 12594
Le si code> sera optimisé, de sorte qu'il est inutile. J'utiliserais également régulièrement
attendre code> au lieu de
waitasync code>, comme cela a le potentiel d'interrupteurs de fil. Que nous ne voulons pas mesurer.
Le verrouillage et le sémaphore mince sont totalement différents et je vous éviterais de les mélanger. Semaphoreslim est bon si vous utilisez Async correctement. P>
Si votre verrou entoure un appel Await, rappelez-vous que le fil qui ramasse fonctionne après un attente ne sera pas nécessairement le même fil qui l'appelait. Il est probable être le même threadcontext mais c'est une chose différente. P>
Également si votre méthode renvoie une tâche et que votre méthode contient une serrure, vous trouverez l'une des threads threadpool utilisés pour exécuter cette tâche sera bloquée jusqu'à ce que la serrure soit libérée, vous pourriez donc finir par affamer n'importe quelle tâche arbitraire quelque part sinon dans votre programme des threads, ils doivent courir. P>
La référence de langue C # dit explicitement que "vous ne pouvez pas utiliser l'opérateur attendu dans le corps d'une déclaration de verrouillage". docs.microsoft.com/en-us/ DotNet / Csharp / Langue-Référence / ...
@Andersemil Bon point mais vous n'avez pas besoin d'utiliser une déclaration de verrouillage pour verrouiller un objet. Vous pouvez utiliser System.Trireading.Monitor ... auquel cas le mélange asynchronisé et le verrouillage s'améliorera probablement mal, à la place de SEMAPHORESLIM sera probablement mieux terminé.
Ceci est intégré à .NET 4.0 et fonctionne bien sur la boîte ..