Udostępnij przez


Kolekcje bezpieczne wątkowo

Przestrzeń nazw System.Collections.Concurrent zawiera kilka klas kolekcji, które są zarówno skalowalne, jak i bezpieczne wątkowo. Wiele wątków może bezpiecznie i wydajnie 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, aby zapisywać wiele wątków równocześnie do kolekcji. Jeśli odczytujesz tylko z kolekcji udostępnionej, użyj klas w System.Collections.Generic przestrzeni nazw.

System.Collections i System.Collections.Generic

Klasy kolekcji w System.Collections przestrzeni nazw obejmują ArrayList i Hashtable. Klasy te zapewniają bezpieczeństwo wątkowe za pośrednictwem właściwości Synchronized, która zwraca bezpieczną wątkowo otokę wokół kolekcji. Wrapper działa poprzez zablokowanie całej kolekcji przy 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 poczekać na objęcie tej jedynej blokady. Ten proces nie jest skalowalny i może spowodować znaczne obniżenie wydajności dużych kolekcji. Ponadto projekt nie jest chroniony przed warunkami wyścigu. Aby uzyskać więcej informacji, zobacz Synchronizacja w kolekcjach ogólnych.

Klasy kolekcji w System.Collections.Generic przestrzeni nazw obejmują List<T> i Dictionary<TKey,TValue>. Klasy te zapewniają lepsze bezpieczeństwo typów danych i wydajność w porównaniu z klasami System.Collections. System.Collections.Generic Jednak klasy nie zapewniają żadnej synchronizacji wątków; kod użytkownika musi zapewnić całą synchronizację, gdy elementy są dodawane lub usuwane jednocześnie w wielu wątkach.

Zalecamy używanie klas kolekcji współbieżnych w System.Collections.Concurrent przestrzeni nazw, ponieważ zapewniają one bezpieczeństwo typów, a także bardziej wydajne i kompletne bezpieczeństwo wątków.

Precyzyjne blokowanie i mechanizmy wolne od blokady

Niektóre typy kolekcji współbieżnych używają uproszczonych mechanizmów synchronizacji, takich jak SpinLock, , SpinWaitSemaphoreSlimi CountdownEvent. Te typy synchronizacji zwykle używają zajętego wirowania przez krótkie okresy, zanim wątek zostanie umieszczony w prawdziwym Wait stanie. Gdy oczekuje się, że czas oczekiwania będzie krótki, przędzenie jest znacznie tańsze obliczeniowo niż oczekiwanie, co wiąże się z kosztownym przejściem jądra. W przypadku klas kolekcji korzystających z wirowania ta wydajność oznacza, że wiele wątków może dodawać i usuwać elementy z 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 używają blokad. Zamiast tego polegają na Interlocked operacjach w celu zapewnienia bezpieczeństwa wątków.

Uwaga / Notatka

Ponieważ klasy kolekcji współbieżnych obsługują ICollection, zapewniają implementacje właściwości IsSynchronized i SyncRoot , mimo że te właściwości są nieistotne. IsSynchronized zawsze zwraca wartość false i SyncRoot jest zawsze null (Nothing w Visual Basic).

Poniższa tabela wymienia typy kolekcji w przestrzeni nazw System.Collections.Concurrent.

Typ Opis
BlockingCollection<T> Zapewnia funkcje ograniczenia i blokowania dla dowolnego typu, który implementuje IProducerConsumerCollection<T>. Aby uzyskać więcej informacji, zobacz BlockingCollection Overview (Omówienie obiektu BlockingCollection).
ConcurrentDictionary<TKey,TValue> Bezpieczna wątkowo implementacja słownika par klucz-wartość.
ConcurrentQueue<T> Bezpieczeństwo wątkowe w implementacji kolejki FIFO (pierwsze weszło, pierwsze wyszło).
ConcurrentStack<T> Bezpieczna dla wątków implementacja stosu LIFO (ostatni na wejściu, pierwszy na wyjściu).
ConcurrentBag<T> Bezpieczna wątkowo implementacja nieurządkowanej kolekcji elementów.
IProducerConsumerCollection<T> Interfejs, który typ musi implementować, aby można było go używać w BlockingCollection.
Nazwa Opis
BlockingCollection — omówienie Opisuje funkcje udostępniane przez BlockingCollection<T> typ.
Instrukcje: dodawanie i usuwanie elementów z elementu ConcurrentDictionary Opisuje sposób dodawania i usuwania elementów z elementu ConcurrentDictionary<TKey,TValue>
Jak dodawać i pobierać poszczególne elementy z kolekcji BlockingCollection Opisuje sposób dodawania i pobierania elementów z kolekcji blokującej bez używania modułu wyliczającego tylko do odczytu.
Instrukcje: dodawanie funkcji ograniczenia i blokowania do kolekcji Opisuje, jak używać dowolnej klasy kolekcji jako podstawowego mechanizmu magazynowania dla kolekcji IProducerConsumerCollection<T>.
Instrukcje: usuwanie elementów w kolekcji BlockingCollection za pomocą narzędzia ForEach W tym artykule opisano sposób używania foreach (For Each w Visual Basic) w celu usunięcia wszystkich elementów w kolekcji blokującej.
Jak używać tablic kolekcji blokujących w potoku Opisuje sposób używania wielu kolekcji blokujących jednocześnie w celu implementacji potoku.
Instrukcje: tworzenie puli obiektów przy użyciu biblioteki ConcurrentBag Pokazuje, jak używać współbieżnego pojemnika w celu zwiększenia wydajności w scenariuszach, w których można ponownie używać istniejących obiektów zamiast stale tworzyć nowe.

Źródło