Quelqu'un peut-il s'il vous plaît expliquer simplement ce que le conflit de fil est?
Je l'ai googlé, mais n'arrive pas à trouver une explication simple.
La querelle de threads est essentiellement une condition dans laquelle un thread attend un verrou/objet 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.
Plusieurs réponses semblent se concentrer sur le conflit de verrous, mais les verrous ne sont pas les seules ressources sur lesquelles des conflits peuvent être expérimentés. La contention consiste simplement lorsque deux threads tentent d'accéder à la même ressource ou à des ressources associées de manière à ce qu'au moins un des threads en conflit s'exécute plus lentement que si les autres threads ne fonctionnaient pas.
L'exemple le plus évident de conflit est sur un verrou. Si le thread A a un verrou et que le thread B souhaite acquérir le même verrou, le thread B devra attendre que le thread A relâche le verrou.
Maintenant, ceci est spécifique à la plate-forme, mais le thread peut connaître des ralentissements même s'il n'a jamais à attendre que l'autre thread libère le verrou! En effet, un verrou protège certaines 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 effectue d'autres tâches. Si deux threads le font, même s'ils ne se disputent jamais pour le verrou, ils peuvent s'exécuter 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 un 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 détecte que les données ne se trouvent pas dans son cache L2 car l'autre processeur a invalidé la ligne de cache. Sur un Pentium D, par exemple, le code s'exécutera à la vitesse FSB, ce qui est nettement inférieur à la vitesse de la mémoire cache L2.
Dans la mesure où un conflit peut survenir même si le verrou n'est pas lui-même contesté, un conflit peut également se produire lorsqu'il n'y a pas de verrou. Par exemple, supposons que votre processeur prenne en charge l’incrémentation atomique d’une variable 32 bits. Si un thread continue à incrémenter et à décrémenter une variable, celle-ci restera chaude dans le cache la plupart du temps. Si deux threads le font, leurs caches vont revendiquer la propriété de la mémoire contenant cette variable et de nombreux accès seront plus lents car le protocole de cohérence de la cache sécurisera chaque propriété principale de la ligne de cache.
Ironiquement, les verrous sont généralement réduits conflits. Pourquoi? Parce que sans un verrou, deux threads pourraient fonctionner sur le même objet ou la même collection et causer beaucoup de conflits (par exemple, il y a des files d'attente libres de verrous). Les verrous auront tendance à désarchiver les threads en conflit, permettant ainsi à des threads non en conflit de s'exécuter. Si le thread A détient un verrou et que le thread B souhaite le même verrou, l'implémentation peut exécuter le thread C à la place. Si le thread C n'a pas besoin de ce verrou, les conflits ultérieurs entre les threads A et B peuvent être évités pendant un certain temps. (Bien entendu, cela suppose que d'autres threads puissent s'exécuter. Cela n'aidera pas si la seule façon dont l'ensemble du système peut progresser efficacement consiste à exécuter des threads conflictuels.)
De ici :
Un conflit survient lorsqu'un thread est en attente d'une ressource qui n'est pas facilement disponible; cela ralentit le exécution de votre code, mais peut effacer au fil du temps.
Un blocage se produit lorsqu'un thread est en attente d'une ressource qu'une seconde le fil est bloqué, et le second Le thread attend une ressource qui le premier thread est bloqué. Plus que deux threads peuvent être impliqués dans un impasse. Une impasse ne résout jamais lui-même. Cela cause souvent le tout application, ou la partie qui est l'expérience de l'impasse, pour arrêter.
Je pense que le PO devrait apporter des éclaircissements sur l’arrière-plan de la question - je peux penser à 2 réponses (bien que je sois sûr que la liste a été complétée):
si vous faites référence au "concept" général de conflit de thread et à la façon dont il peut se présenter dans une application, je me reporte à la réponse détaillée de @ DavidSchwartz ci-dessus.
Il existe également le compteur de performances '.NET CLR Locks and Threads: Nombre total de contenus'. D'après la description de PerfMon pour ce compteur, il est défini comme suit:
Ce compteur affiche le nombre total de fois que les threads du CLR ont tenté d'acquérir un verrou géré sans succès. Les serrures gérées peuvent être acquises de plusieurs façons. par l'instruction "lock" en C # ou en appelant System.Monitor.Enter ou en utilisant l'attribut personnalisé MethodImplOptions.Synchronized.
... et je suis sûr que d'autres pour d'autres OS 'et les cadres d'application.
Vous avez 2 discussions. Fil A et Fil B, vous avez aussi l'objet C.
A accède actuellement à l'objet C et a verrouillé cet objet. B a besoin d'accéder à l'objet C, mais ne peut le faire que lorsque A relâche le verrou sur l'objet C.
Un autre mot pourrait être simultané. C'est simplement l'idée de deux ou plusieurs threads essayant d'utiliser la même ressource.
Pour moi, la contention est une compétition entre 2 ou plusieurs threads sur une ressource partagée. La 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 conflit. Plus l'accès à une ressource est fréquent, plus il y a de conflits.
Les conflits de threads sont également affectés par les opérations d'E/S. Exemple lorsqu'un thread en attente de lecture de fichier peut être considéré comme un conflit. Utilisez les ports d’achèvement des E/S comme solution.
Imaginez le scénario suivant. Vous vous préparez pour la finale de demain examinez et sentez-vous un peu faim. Alors, vous donnez à votre jeune frère Dix dollars et lui demander d'acheter une pizza pour vous. Dans ce cas, vous êtes le fil principal et votre frère est un fil enfant. Une fois que votre commande est étant donné que vous et votre frère faites leur travail simultanément (c'est-à-dire étudier et acheter une pizza). Maintenant, nous avons deux cas à considérer. D'abord, votre frère ramène votre pizza et se termine pendant que vous étudiez. Dans ce cas, vous pouvez arrêter d'étudier et profiter de la pizza. Deuxièmement, vous terminez vos études tôt et vous dormez (c’est-à-dire que votre travail assigné pour aujourd'hui (étudier pour le dernier examen de demain) est terminé) avant que la pizza est disponible. Bien sûr, vous ne pouvez pas dormir. autrement, vous n'aurez pas la chance de manger la pizza. Ce que vous allez faire est attendre que ton frère ramène la pizza.
Comme dans l'exemple, les deux cas donnent un sens à la rivalité.
Le conflit de verrouillage a lieu lorsqu'un thread tente d'acquérir le verrou sur un objet qui est déjà acquis par un autre thread *. Jusqu'à l'objet est libéré, le thread est bloqué (en d’autres termes, il est dans l’état En attente). Dans certains cas, cela peut conduire à une série dite exécution qui affecte négativement l'application.
à partir de documentation dotTrace