W normalnych warunkach, dopóki zaangażowane jest programowanie wielowątkowe, złożoność programu znacznie wzrośnie, wydajność znacznie spadnie, a prawdopodobieństwo błędów znacznie wzrośnie.
Programowanie wielowątkowe ma na celu uruchomienie programu równolegle w celu poprawy możliwości przetwarzania danych, ale w większości przypadków wiąże się z rywalizacją o współdzielone zasoby, dlatego musi być zablokowane podczas modyfikowania obiektów zasobów. Jednak istnieje wiele sposobów implementacji blokad, więc przyjrzyjmy się implementacji i wydajności kilku typów blokad w C#.
Kilka sposobów wykorzystania zamków
1. Zamek atomowy
Osiągnij "bezblokadową" konkurencję poprzez operację atomową Interlocked.CompareExchange.
Oficjalne wyjaśnienie polega na udostępnieniu atomowych operacji dla zmiennych współdzielonych przez wiele wątków. Przestrzeń nazw: System.Threading
2. Obszar krytyczny
Serializacja wielu wątków w celu uzyskania dostępu do zasobów publicznych lub fragmentu kodu jest szybka i odpowiednia do kontrolowania dostępu do danych. Składnia blokady w C# to składnia cukrowa dla obszaru krytycznego (Monitor).
3. Działanie atomowe
Operacje atomowe, które są szczególnym przypadkiem, są z natury bezpieczne dla wątków, więc nie ma potrzeby ich blokować.
Oficjalnie interpretowane jako zwiększanie wartości danej zmiennej w formie operacji atomowej i przechowywanie wyniku. Przestrzeń nazw: System.Threading
4. Blokada odczytu i zapisu
Blokady odczytu i zapisu pozwalają na odczyt zasobów podczas zapisu innych programów, więc jeśli zasób pozwala na nieczytelne odczyty, jest to bardziej odpowiednie.
Oficjalne wyjaśnienie wskazuje na stan zablokowany używany do zarządzania dostępem do zasobów, umożliwiający wielowątkowe odczyty lub wyłączny dostęp do zapisu. Przestrzeń nazw to System.Threading
5. Semafor
Semafory, zaprojektowane do kontroli ograniczonej liczby zasobów użytkowników.
Oficjalne wyjaśnienie ogranicza liczbę wątków, które mogą jednocześnie uzyskać dostęp do zasobu lub puli zasobów. Przestrzeń nazw to System.Threading
6. Wydarzenia
Używany do powiadamiania wątku o wystąpieniu pewnych zdarzeń, rozpoczynając rozpoczęcie zadania następnego.
Oficjalne wyjaśnienie mówi, że zdarzenia synchronizacji wątków automatycznie resetują się, gdy sygnał zostanie odebrany po jego zwolnieniu. Takich typów nie można dziedziczyć.
7. Wzajemne wykluczenie
W C# znajduje się klasa Mutex, tuż pod przestrzenią nazw System.Threading, Mutex jest w rzeczywistości mutexem, który nie tylko radzi sobie z konkurencją zasobów między wieloma wątkami, ale także z konkurencją zasobów między procesami.
Kod testów wydajności
Uruchom kod
Wyniki testów wydajności
Uwaga: Powyższe dane są jedynie wynikiem wydajności sprzętowej aktualnego środowiska testowego i można je jedynie ze sobą porównywać.
1) W różnych testach zdecydowanie najszybciej się nie blokuje, więc staraj się unikać konkurencji zasobów, która prowadzi do zablokowanej operacji.
2) Interlocked.CompareExchange konsekwentnie wykazuje lepsze wyniki w wielowątkowości, zajmując drugie miejsce.
3) Trzecia blokada, strefa krytyczna, również wykazuje dobrą wydajność, więc proszę zaprzeczać innym, którzy twierdzą, że wydajność blokady jest niska.
4) Czwarte miejsce to operacja zmiennych atomowych (atomowa), ale obecnie wspiera jedynie samoprzyrost i odejmowanie zmiennych, a zastosowanie nie jest silne.
5) Wydajność piątego blokady odczytu/zapisu (ReaderWriterLockSlim) również jest w porządku, obsługuje odczyt nic, a praktyczność jest nadal stosunkowo dobra.
6) Pozostałe semafory, wydarzenia i mutex mają oczywiście najgorsze wyniki, mają własne zakresy zastosowań, ale nie radzą sobie dobrze w walce z zasobami.
Oryginalny adres linku:Logowanie do linku jest widoczne.
|