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.
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.

Tematy pomocy

System.Collections.Concurrent