143 votes

Qu'est-ce que la contention de fil ?

Quelqu'un peut-il expliquer simplement ce qu'est la contention de fil ?

J'ai fait des recherches sur Internet, mais je n'ai pas trouvé d'explication simple.

224voto

David Schwartz Points 70129

Plusieurs réponses semblent se concentrer sur la contention des verrous, mais les verrous ne sont pas les seules ressources sur lesquelles il peut y avoir de la contention. On parle de contention lorsque deux threads tentent d'accéder à la même ressource ou à des ressources connexes de telle sorte qu'au moins un des threads en compétition fonctionne plus lentement que si le ou les autres threads ne fonctionnaient pas.

L'exemple le plus évident de contention est celui d'un verrou. Si le thread A possède un verrou et que le thread B veut acquérir ce même verrou, le thread B devra attendre que le thread A libère le verrou.

Cela dépend de la plate-forme, mais le thread peut subir des ralentissements même s'il ne doit jamais attendre que l'autre thread libère le verrou ! En effet, un verrou protège un certain type de données, et les données elles-mêmes sont souvent contestées.

Par exemple, considérons un thread qui acquiert un verrou, modifie un objet, puis libère le verrou et fait d'autres choses. Si deux threads font cela, même s'ils ne se battent jamais pour le verrou, les threads peuvent fonctionner beaucoup plus lentement que si un seul thread était en cours d'exécution.

Pourquoi ? Supposons que chaque thread s'exécute sur son propre cœur sur un processeur x86 moderne et que les cœurs ne partagent pas de cache L2. Avec un seul thread, l'objet peut rester dans le cache L2 la plupart du temps. Avec les deux threads en cours d'exécution, chaque fois qu'un thread modifie l'objet, l'autre thread constatera que les données ne sont pas dans son cache L2 parce que l'autre CPU a invalidé la ligne de cache. Sur un Pentium D, par exemple, cela entraînera l'exécution du code à la vitesse du FSB, qui est bien inférieure à celle du cache L2.

Puisque la contention peut se produire même si le verrou n'est pas lui-même sollicité, la contention peut également se produire lorsqu'il n'y a pas de verrou. Par exemple, disons que votre CPU supporte l'incrémentation atomique d'une variable de 32 bits. Si un thread continue d'incrémenter et de décrémenter une variable, la variable sera chaude dans le cache la plupart du temps. Si deux threads le font, leurs caches vont se disputer la propriété de la mémoire contenant cette variable, et de nombreux accès seront plus lents car le protocole de cohérence du cache opère pour garantir à chaque noyau la propriété de la ligne de cache.

Ironiquement, les verrous sont généralement réduire le site la contention. Pourquoi ? Parce que sans verrou, deux threads pourraient opérer sur le même objet ou la même collection et causer beaucoup de contention (par exemple, il existe des files d'attente sans verrou). Les verrous auront tendance à désordonner les threads en conflit, permettant aux threads non en conflit de s'exécuter à la place. Si le thread A détient un verrou et que le thread B veut ce même verrou, l'implémentation peut faire tourner le thread C à la place. Si le thread C n'a pas besoin de ce verrou, les conflits futurs entre les threads A et B peuvent être évités pendant un certain temps. (Bien sûr, cela suppose qu'il existe d'autres threads qui pourraient être exécutés. Cela ne servira à rien si la seule façon pour le système dans son ensemble de faire des progrès utiles est d'exécuter des threads qui se disputent).

107voto

keyboardP Points 44625

Essentiellement, la contention de threads est une condition dans laquelle un thread attend un verrou/objet qui est actuellement détenu par un autre thread. Par conséquent, ce thread en attente ne peut pas utiliser cet objet tant que l'autre thread n'a pas déverrouillé cet objet particulier.

24voto

Jon B Points 26872

De aquí :

Une contention se produit lorsqu'un thread est attend une ressource qui n'est pas disponible ; cela ralentit l'exécution l'exécution de votre code, mais elle peut se résorber avec le temps.

Une impasse se produit lorsqu'un thread est attend une ressource qu'un second thread a verrouillé, et que le second deuxième thread attend une ressource que que le premier thread a verrouillé. Plus de deux threads peuvent être impliqués dans un blocage. Une impasse ne se résout jamais jamais. Elle entraîne souvent l'arrêt de toute l'application, ou la partie qui partie qui subit le blocage, s'arrête.

4voto

Dave Black Points 1396

Je pense que l'OP devrait clarifier le contexte de la question. Je peux penser à deux réponses (mais je suis sûr qu'il y a des ajouts à cette liste) :

  1. si vous faites référence au "concept" général de contention de fil et à la façon dont il peut se présenter dans une application, je m'en remets à la réponse détaillée de @DavidSchwartz ci-dessus.

  2. Il y a aussi le compteur de performance '.NET CLR Locks and Threads:Total # of Contentions'. D'après la description de PerfMon pour ce compteur, il est défini comme suit :

    Ce compteur affiche le nombre total de fois où les threads du CLR ont tenté d'acquérir un verrou géré sans succès. Les verrous gérés peuvent être acquis de plusieurs façons : par l'instruction "lock" en C#, en appelant System.Monitor.Enter ou en utilisant l'attribut personnalisé MethodImplOptions.Synchronized.

...et je suis sûr qu'il y en a d'autres pour d'autres OS et cadres d'application.

3voto

Maciej Points 3666

Pour moi, la contention est une compétition entre 2 ou plusieurs threads pour une ressource partagée. Cette ressource peut être un verrou, un compteur, etc. La compétition signifie "qui l'obtient en premier". Plus il y a de threads, plus il y a de contention. Plus l'accès à une ressource est fréquent, plus la contention est importante.

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