Kolekcje bezpieczne wątkowo
W .NET Framework 4 wprowadzono System.Collections.Concurrent przestrzeń nazw, która obejmuje kilka klas kolekcji, które są bezpieczne wątkowo i skalowalne. Wiele wątków może bezpiecznie i efektywnie dodawać lub usuwać elementy z tych kolekcji bez konieczności dodatkowej synchronizacji w kodzie użytkownika. Podczas pisania nowego kodu użyj współbieżnych klas kolekcji, gdy wiele wątków będzie zapisywać w kolekcji jednocześnie. Jeśli z udostępnionej kolekcji odbywa się tylko odczyt, można używać klas z przestrzeni nazw System.Collections.Generic. Zalecamy nieużywanie klas kolekcji w wersji 1.0, chyba że aplikacje mają być przeznaczone dla środowiska uruchomieniowego .NET Framework 1.1 lub starszego.
Synchronizacja wątków w kolekcjach środowisk .NET Framework 1.0 i 2.0
Kolekcje wprowadzone w środowisku .NET Framework 1.0 znajdują się w przestrzeni nazw System.Collections. Kolekcje te, wśród których są m.in. powszechnie używane ArrayList i Hashtable, oferują pewne bezpieczeństwo wątkowe za pomocą właściwości Synchronized
, która zwraca bezpieczną wątkowo otokę wokół kolekcji. Otoka działa w ten sposób, że blokuje całą kolekcję podczas każdej operacji dodawania lub usuwania. W związku z tym każdy wątek, który próbuje uzyskać dostęp do kolekcji, musi czekać na swoją kolej, aby nałożyć jedną blokadę. Takie rozwiązanie nie jest skalowalne i przy dużych kolekcjach może powodować znaczne pogorszenie wydajności. Ponadto konstrukcja nie jest całkowicie chroniona przed sytuacjami wyścigu. Aby uzyskać więcej informacji, zobacz Synchronizacja w kolekcjach ogólnych.
Klasy kolekcji wprowadzone w środowisku .NET Framework 2.0 są umieszczone w przestrzeni nazw System.Collections.Generic. Należą do nich List<T>, Dictionary<TKey,TValue> itd. Te klasy oferują większe bezpieczeństwo pod względem typów i lepszą wydajność niż klasy środowiska .NET Framework 1.0. Jednak klasy kolekcji środowiska .NET Framework 2.0 nie zawierają żadnych funkcji synchronizacji wątków. Gdy elementy są dodawane lub usuwane równolegle w wielu wątkach, całą synchronizację musi zapewniać kod użytkownika.
Zalecamy współbieżne klasy kolekcji w .NET Framework 4, ponieważ zapewniają one nie tylko bezpieczeństwo typów klas kolekcji .NET Framework 2.0, ale także bardziej wydajne i bardziej kompletne bezpieczeństwo wątków niż zapewniają kolekcje .NET Framework 1.0.
Blokowanie szczegółowe i mechanizmy bezblokadowe
Niektóre z typów kolekcji współbieżnych używają lekkich mechanizmów synchronizacji, takich jak SpinLock, SpinWait, SemaphoreSlimi CountdownEvent, które są nowe w .NET Framework 4. Te typy synchronizacji zwykle używają zajętego wirowania w krótkich okresach przed umieszczeniem wątku w prawdziwym stanie oczekiwania. Jeśli spodziewane czasy oczekiwania będą bardzo krótkie, warto stosować rotowanie, ponieważ znacznie mniej obciąża ono zasoby systemu niż przejścia jądra występujące w czekaniu. W przypadku klas kolekcji wykorzystujących mechanizm rotowania lepsza wydajność oznacza możliwość dodawania i usuwania elementów równolegle przez wiele wątków z bardzo dużą szybkością. Aby uzyskać więcej informacji na temat wirowania i blokowania, zobacz SpinLock i SpinWait.
Klasy ConcurrentQueue<T> i ConcurrentStack<T> w ogóle nie nakładają blokad. Zamiast tego do zapewnienia bezpieczeństwa wątkowego wykorzystują operacje Interlocked.
Uwaga
Ponieważ klasy kolekcji współbieżnych obsługują interfejs ICollection, implementują one właściwości IsSynchronized i SyncRoot, nawet jeśli te właściwości są nieistotne. Właściwość IsSynchronized
zawsze zwraca wartość false
, a właściwość SyncRoot
zawsze ma wartość null
(Nothing
w języku Visual Basic).
W tabeli poniżej wymieniono typy kolekcji istniejące w przestrzeni nazw System.Collections.Concurrent.
Typ | Opis |
---|---|
BlockingCollection<T> | Zapewnia funkcjonalność ograniczania i blokowania dla wszystkich typów implementujących interfejs IProducerConsumerCollection<T>. Aby uzyskać więcej informacji, zobacz BlockingCollection Overview (Omówienie funkcji BlockingCollection). |
ConcurrentDictionary<TKey,TValue> | Bezpieczna wątkowo implementacja słownika par klucz-wartość. |
ConcurrentQueue<T> | Bezpieczna wątkowo implementacja kolejki FIFO („pierwszy na wejściu, pierwszy na wyjściu”). |
ConcurrentStack<T> | Bezpieczna wątkowo implementacja stosu LIFO („ostatni na wejściu, pierwszy na wyjściu”). |
ConcurrentBag<T> | Bezpieczna wątkowo implementacja nieuporządkowanej kolekcji elementów. |
IProducerConsumerCollection<T> | Interfejs, który musi implementować typ, aby mógł być używany w klasie BlockingCollection . |
Tematy pokrewne
Tytuł | Opis |
---|---|
BlockingCollection — Przegląd | Opisuje funkcje zawarte w typie BlockingCollection<T>. |
Instrukcje: Dodawanie elementów do kolekcji ConcurrentDictionary i ich usuwanie | Opisuje metody dodawania i usuwania elementów w klasie ConcurrentDictionary<TKey,TValue>. |
Instrukcje: Dodawanie i pobieranie elementów osobno w ramach kolekcji BlockingCollection | Opisuje metody dodawania i pobierania elementów z kolekcji blokującej bez używania modułu wyliczającego z właściwością tylko do odczytu. |
Instrukcje: Dodawanie funkcji blokujących i ograniczających do kolekcji | Opisuje wykorzystywanie klas kolekcji jako podstawowego mechanizmu przechowywania dla kolekcji IProducerConsumerCollection<T>. |
Instrukcje: Używanie metody ForEach do usuwania elementów z kolekcji BlockingCollection | Opisuje zastosowanie instrukcji foreach (For Each w języku Visual Basic) do usuwania wszystkich elementów w kolekcji blokującej. |
Instrukcje: Używanie tablic kolekcji blokujących w potoku | Opisuje zastosowanie wielu kolekcji blokujących równocześnie w celu zaimplementowania potoku. |
Instrukcje: Tworzenie puli obiektów przy użyciu obiektu ConcurrentBag | Pokazuje, jak za pomocą współbieżnego zbioru poprawić wydajność w scenariuszach, gdzie można wykorzystywać istniejące obiekty zamiast ciągle tworzyć nowe. |