Odpowiedzi:
Zasadniczo rywalizacja wątków jest stanem, w którym jeden wątek oczekuje na blokadę / obiekt, który jest obecnie utrzymywany przez inny wątek. Dlatego ten wątek oczekujący nie może używać tego obiektu, dopóki inny wątek nie odblokuje tego konkretnego obiektu.
Wydaje się, że kilka odpowiedzi koncentruje się na rywalizacji o blokady, ale blokady nie są jedynymi zasobami, w przypadku których można doświadczyć rywalizacji. Rywalizacja polega po prostu na tym, że dwa wątki próbują uzyskać dostęp do tego samego zasobu lub powiązanych zasobów w taki sposób, że co najmniej jeden z rywalizujących wątków działa wolniej, niż gdyby nie działały inne wątki.
Najbardziej oczywistym przykładem niezgody jest zamek. Jeśli wątek A ma blokadę i wątek B chce uzyskać tę samą blokadę, wątek B będzie musiał poczekać, aż wątek A zwolni blokadę.
Teraz jest to specyficzne dla platformy, ale wątek może ulec spowolnieniu, nawet jeśli nigdy nie będzie musiał czekać, aż inny wątek zwolni blokadę! Dzieje się tak, ponieważ blokada chroni pewne rodzaje danych, a same dane często również są przedmiotem rywalizacji.
Na przykład rozważmy wątek, który uzyskuje blokadę, modyfikuje obiekt, a następnie zwalnia blokadę i robi inne rzeczy. Jeśli robią to dwa wątki, nawet jeśli nigdy nie walczą o blokadę, mogą one działać znacznie wolniej niż gdyby działał tylko jeden wątek.
Czemu? Powiedzmy, że każdy wątek działa na własnym rdzeniu na nowoczesnym procesorze x86, a rdzenie nie współużytkują pamięci podręcznej L2. Mając tylko jeden wątek, obiekt może pozostawać w pamięci podręcznej L2 przez większość czasu. Gdy oba wątki są uruchomione, za każdym razem, gdy jeden wątek modyfikuje obiekt, drugi wątek stwierdzi, że dane nie znajdują się w jego pamięci podręcznej L2, ponieważ inny procesor unieważnił linię pamięci podręcznej. Na przykład na Pentium D spowoduje to działanie kodu z szybkością FSB, która jest znacznie mniejsza niż szybkość pamięci podręcznej L2.
Ponieważ rywalizacja może wystąpić nawet wtedy, gdy sama blokada nie jest przedmiotem rywalizacji, rywalizacja może również wystąpić, gdy nie ma blokady. Na przykład załóżmy, że Twój procesor obsługuje atomową inkrementację zmiennej 32-bitowej. Jeśli jeden wątek ciągle zwiększa i zmniejsza wartość zmiennej, zmienna będzie przez większość czasu gorąca w pamięci podręcznej. Jeśli zrobią to dwa wątki, ich pamięci podręczne będą walczyć o własność pamięci przechowującej tę zmienną, a wiele dostępów będzie wolniejszych, ponieważ protokół spójności pamięci podręcznej działa w celu zabezpieczenia własności każdego rdzenia linii pamięci podręcznej.
Jak na ironię, zamki zazwyczaj zmniejszają rywalizację. Czemu? Ponieważ bez blokady dwa wątki mogłyby działać na tym samym obiekcie lub kolekcji i powodować wiele rywalizacji (na przykład istnieją kolejki bez blokad). Blokady będą miały tendencję do usuwania harmonogramu wątków rywalizujących, umożliwiając zamiast tego uruchamianie wątków nie rywalizujących. Jeśli wątek A przechowuje blokadę, a wątek B chce tej samej blokady, implementacja może zamiast tego uruchomić wątek C. Jeśli wątek C nie potrzebuje tej blokady, można przez chwilę uniknąć przyszłej rywalizacji między wątkami A i B. (Oczywiście przy założeniu, że istnieją inne wątki, które mogą działać. Nie pomoże, jeśli jedynym sposobem, w jaki system jako całość może zrobić użyteczny postęp, będzie uruchamianie wątków, które rywalizują).
Od tutaj :
Rywalizacja występuje, gdy wątek oczekuje na zasób, który nie jest łatwo dostępny; spowalnia wykonywanie kodu, ale może z czasem ulec wyjaśnieniu.
Zakleszczenie występuje, gdy wątek oczekuje na zasób, który został zablokowany przez drugi wątek, a drugi wątek oczekuje na zasób, który został zablokowany przez pierwszy wątek. Zakleszczenie może obejmować więcej niż dwa wątki. Impas nigdy nie ustępuje sam. Często powoduje zatrzymanie całej aplikacji lub części, w której występuje impas.
Myślę, że w kontekście tego pytania powinno być jakieś wyjaśnienie z PO - przychodzą mi do głowy 2 odpowiedzi (chociaż jestem pewien, że są dodatki do tej listy):
jeśli odnosisz się do ogólnej „koncepcji” rywalizacji o wątki i tego, jak może ona prezentować się w aplikacji, odwołam się do szczegółowej odpowiedzi @ DavidSchwartz powyżej.
Istnieje również licznik wydajności „.NET CLR Locks and Threads: Total # of Contentions”. Jak zaczerpnięto z opisu PerfMon dla tego licznika, jest on zdefiniowany jako:
Ten licznik wyświetla całkowitą liczbę razy, kiedy wątki w środowisku CLR próbowały uzyskać zarządzaną blokadę bez powodzenia. Zarządzane zamki można zdobyć na wiele sposobów; przez instrukcję „lock” w C # lub wywołując System.Monitor.Enter lub używając atrybutu niestandardowego MethodImplOptions.Synchronized.
... i jestem pewien, że inne dla innych systemów operacyjnych i frameworków aplikacji.
Innym słowem może być współbieżność. Jest to po prostu idea dwóch lub więcej wątków próbujących użyć tego samego zasobu.
Wyobraź sobie następujący scenariusz. Przygotowujesz się do jutrzejszego egzaminu końcowego i czujesz się trochę głodny. Więc daj swojemu młodszemu bratu dziesięć dolców i poproś go, żeby kupił ci pizzę. W tym przypadku jesteś głównym wątkiem, a twój brat jest wątkiem podrzędnym. Po otrzymaniu zamówienia zarówno ty, jak i twój brat wykonujesz swoją pracę jednocześnie (np. Uczą się i kupują pizzę). Teraz mamy do rozważenia dwa przypadki. Po pierwsze, twój brat przynosi twoją pizzę i kończy naukę. W takim przypadku możesz przestać się uczyć i cieszyć się pizzą. Po drugie, kończysz naukę wcześnie i śpisz (tj. Twoja przydzielona praca na dziś - nauka do jutrzejszego egzaminu końcowego - jest wykonana), zanim pizza będzie dostępna. Oczywiście nie możesz spać; w przeciwnym razie nie będziesz miał okazji zjeść pizzy.
Tak jak w przykładzie, oba przypadki nadają sens rywalizacji.
Rywalizacja o blokadę ma miejsce, gdy wątek próbuje uzyskać blokadę do obiektu, który został już przejęty przez inny wątek *. Do momentu zwolnienia obiektu wątek jest blokowany (innymi słowy jest w stanie Oczekiwanie). W niektórych przypadkach może to prowadzić do tak zwanego wykonywania seryjnego, co negatywnie wpływa na aplikację.