Szálbiztos gyűjtemények

A System.Collections.Concurrent névtér több olyan gyűjteményosztályt tartalmaz, amelyek szálbiztosak és méretezhetők is. Több szál is biztonságosan és hatékonyan adhat hozzá vagy távolíthat el elemeket ezekből a gyűjteményekből anélkül, hogy további szinkronizálást kellene igényelnie a felhasználói kódban. Új kód írásakor az egyidejű gyűjteményosztályokkal egyszerre több szálat is írhat a gyűjteménybe. Ha csak megosztott gyűjteményből olvas, használja a System.Collections.Generic névtérben lévő osztályokat.

System.Collections és System.Collections.Generic

A System.Collections névtérben a gyűjteményosztályok közé tartozik a ArrayList és a Hashtable. Ezek az osztályok némi szálbiztonságot biztosítanak a Synchronized tulajdonságon keresztül, amely egy szálbiztos burkolót ad vissza a gyűjtemény körül. A burkoló úgy működik, hogy minden hozzáadási vagy eltávolítási műveletnél zárolja a teljes gyűjteményt. Ezért minden szálnak, amely megkísérli elérni a gyűjteményt, meg kell várnia a sorát, hogy megszerezze az egyetlen zárat. Ez a folyamat nem skálázható, és jelentős teljesítménycsökkenést okozhat a nagy gyűjtemények esetében. Emellett a kialakítás nem védve van a versenyfeltételektől. További információ: Szinkronizálás általános gyűjteményekben.

A System.Collections.Generic névtérben a gyűjteményosztályok közé tartozik a List<T> és a Dictionary<TKey,TValue>. Ezek az osztályok jobb típusbiztonságot és teljesítményt biztosítanak az System.Collections osztályokhoz képest. Az System.Collections.Generic osztályok azonban nem biztosítanak szálszinkronizálást; a felhasználói kódnak minden szinkronizálást meg kell adnia, ha az elemek egyszerre több szálon vannak hozzáadva vagy eltávolítva.

Javasoljuk, hogy az egyidejű gyűjteményosztályokat használja a System.Collections.Concurrent névtérben, mert típusbiztonságot, valamint hatékonyabb és teljesebb szálbiztonságot biztosítanak.

Részletes zárolási és zárolásmentes megoldások

Az egyidejű gyűjteménytípusok némelyike egyszerűsített szinkronizálási mechanizmusokat használ, például SpinLock: , SpinWaitSemaphoreSlimés CountdownEvent. Ezek a szinkronizálási típusok tipikusan foglalt pörgetést használnak rövid időszakokra, mielőtt a szálat valódi Wait állapotba helyezik. Amikor a várakozási idő várhatóan rövid, a pörgés sokkal kevésbé költséges a számítási teljesítmény szempontjából, mint a várakozás, amely drága kernelátmenetet igényel. A forgót használó gyűjteményosztályok esetében ez a hatékonyság azt jelenti, hogy több szál is nagy sebességgel adhat hozzá és távolíthat el elemeket. További információ a pörgetésről és a blokkolásról: SpinLock és SpinWait.

Az ConcurrentQueue<T> osztályok és ConcurrentStack<T> osztályok egyáltalán nem használnak zárakat. Ehelyett a szálbiztonság érdekében a műveletekre Interlocked támaszkodnak.

Megjegyzés:

Mivel az egyidejű gyűjteményosztályok támogatják ICollection, implementációkat biztosítanak a IsSynchronized tulajdonságokhoz, SyncRoot annak ellenére, hogy ezek a tulajdonságok irrelevánsak. IsSynchronized mindig visszatér false, és SyncRoot mindig null (Nothing a Visual Basicben).

Az alábbi táblázat a System.Collections.Concurrent névtér gyűjteménytípusait sorolja fel:

Típus Leírás
BlockingCollection<T> Határoló és blokkoló funkciókat biztosít minden típushoz, amely az IProducerConsumerCollection<T>-t implementálja. További információ: BlockingCollection – Áttekintés.
ConcurrentDictionary<TKey,TValue> Kulcs-érték párok szótárának szálbiztos implementálása.
ConcurrentQueue<T> A szálbiztos FIFO (első be, első ki) sor implementálása.
ConcurrentStack<T> Szálbiztos LIFO (utolsó be, első ki) verem megvalósítása.
ConcurrentBag<T> Az elemek nem rendezett gyűjteményének szálbiztos implementálása.
IProducerConsumerCollection<T> Az a felület, amelyet egy típusnak implementálnia kell ahhoz, hogy egy BlockingCollection-ben használható legyen.
Cím Leírás
A(z) BlockingCollection áttekintése A típus által BlockingCollection<T> biztosított funkciókat ismerteti.
Útmutató: Elemek hozzáadása és eltávolítása egy konkurrens szótárból Azt ismerteti, hogyan vehet fel és távolíthat el elemeket a ConcurrentDictionary<TKey,TValue>
Útmutató: Elemek hozzáadása és felvétele egyenként a BlockingCollectionből Azt ismerteti, hogyan adhat hozzá és kérhet le elemeket egy blokkolási gyűjteményből írásvédett enumerátor használata nélkül.
Útmutató: Határoló és blokkoló funkciók hozzáadása gyűjteményhez Azt ismerteti, hogyan használható bármely gyűjteményosztály a gyűjtemény alapjául szolgáló IProducerConsumerCollection<T> tárolási mechanizmusként.
Útmutató: A ForEach használata a BlockingCollection elemeinek eltávolításához Ez a cikk azt ismerteti, hogyan távolíthatja foreach el a blokkoló gyűjtemény összes elemét (For Each a Visual Basicben).
Hogyan használjuk: Blokkoló gyűjtemények tömbjeit csővezetékben Azt ismerteti, hogyan lehet egyszerre több blokkoló gyűjteményt használni egy folyamat implementálásához.
Útmutató: Objektumkészlet létrehozása a ConcurrentBag használatával Bemutatja, hogyan javíthatja a teljesítményt egy egyidejű zsák használatával olyan helyzetekben, ahol az objektumok újra felhasználhatók az újak folyamatos létrehozása helyett.

Referenciák