2011-06-22 5 views
13

ConcurrentBag pozwoli wielu wątkom dodawać i usuwać przedmioty z torby. Możliwe, że wątek doda przedmiot do torby, a następnie w końcu zabiera go z powrotem. Mówi, że ConcurrentBag jest nieuporządkowana, ale jak nieuporządkowane? W jednym wątku worek działa jak stos. Czy nieuporządkowany oznacza "nie jak połączona lista"?Co to jest wykorzystanie w świecie rzeczywistym dla ConcurrentBag <T>?

Jaki jest prawdziwy świat za korzystanie ConcurrentBag?

+5

Co masz na myśli „jak to jest nieuporządkowana”? Jest albo określony porządek, albo nie ma go. To tak, jakby powiedzieć "Jak martwy jest Elvis?" –

+0

Kolejność przechowywanych elementów nie należy do firmy klienta. Zatem z punktu widzenia API "nieuporządkowane" zawsze odnosi się do kolejności wyliczania (z metody "GetEnumerator"). –

+3

"brak zamówienia" oznacza, że ​​nie ma żadnych gwarancji dotyczących zamówienia.Obecne zachowanie implementacji wydaje się polegać na tym, że działa jak stos, gdy ten sam wątek dodaje i usuwa, i podobnie jak kolejka, gdy jeden wątek pobiera z innej kolekcji. Ale nie liczyłbym na to zachowanie. Zobacz http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=842, aby uzyskać więcej informacji. 'ConcurrentBag' może dać lepszą wydajność niż' ConcurrentQueue', jeśli kolejność nie jest ważna, a wątki mogą być zarówno producentem, jak i konsumentem. –

Odpowiedz

3

Torby są bardzo przydatne do śledzenia liczby instancji. Na przykład, jeśli chcesz prowadzić rejestr hostów, dla których obsługujesz żądania internetowe, możesz dodać ich adres IP do torby po rozpoczęciu obsługi żądania i usunąć go po zakończeniu.

Korzystanie torbę pozwoli Ci powiedzieć na pierwszy rzut oka, które IPS aktualnie serwisowych. Pozwoli to również szybko zapytać, czy obsługujesz dany adres IP.

W przypadku korzystania z zestawu do tego raczej niż worek, następnie po wielu jednoczesnych żądań z tego samego adresu IP będzie bałagan swojej ewidencji.

+7

Mówisz, dodaj swoje IP do torby, a następnie usuń je, kiedy skończysz. Jak usunąć konkretny przedmiot z torby? –

+2

@Dustin: Dobre pytanie. Myślałem o ['ConcurrentHashMultiset'] (https://guava-libraries.googlecode.com/svn/tags/release09/javadoc/com/google/common/collect/ConcurrentHashMultiset.html) (Java odpowiednik' ConcurrentBag'), kiedy pisałem swoją odpowiedź, która ma "metodę usuwania". Nie mam pojęcia, do czego służy klasa .NET 'ConcurrentBag'. :-P –

+2

To wszystko w porządku, na podstawie Twojej odpowiedzi udało mi się wymyślić scenariusz z prawdziwego świata, który dotyczy mnie. –

1

Wszystko, gdzie po prostu trzeba śledzić, co tam jest i nie potrzebują dostępu losowego lub gwarantowane zamówienia. Jeśli masz wątek, który dodaje elementy do przetworzenia, i wątek, który usuwa elementy w celu ich przetworzenia, współbieżna torba będzie działała dobrze, jeśli nie obchodzi cię, że są przetwarzane w kolejności FIFO.

+3

Scenariusz z prawdziwego świata ... –

1

Dzięki @Chris Jester-Young wymyśliłem dobrego, prawdziwego świata, scenariusz, który rzeczywiście odnosi się do projektu pracuję nad.

Find - Proces - sklep

Znajdź - nić 1 & 2 są ustawione, aby znaleźć lub zeskrobać danych (system plików, WWW, itp). Wyniki te są przechowywane w aplikacji ConcurrentBag1.

Sposób - nić 3 & 4 są ustawione wyjąć z ConcurrentBag1, czysty/przekształcenie/przetwarzania danych, a następnie zapisać wyniki w ConcurrentBag2.

Sklep - wątki 5 jest zestaw do zbierania wyników z ConcurrentBag2 i przechowywania wyników w SQL.

+0

Z opisu wydaje się, że lepiej byłoby zaimplementować za pomocą kolejkowania warstwowego (prawdopodobnie instancji 'ConcurrentQueue' lub' BlockingCollection') zamiast klasy 'ConcurrentBag'. Wydaje się, że istnieje sporo nakładania się użycia klasy, więc mogę się mylić. –

12

Ponieważ nie ma ConcurrentBag Zamawiający ma przewagę wydajności nad ConcurrentStack/kolejki. Jest on zaimplementowany przez firmę Microsoft jako lokalny magazyn wątków. Tak więc każdy wątek, który dodaje elementy, robi to w swojej własnej przestrzeni. Podczas pobierania elementów pochodzą one z lokalnego magazynu. Dopiero gdy jest pusty, wątek kradnie przedmiot z innego magazynu wątków. Zamiast więc prostej listy, ConcurrentBag jest rozproszoną listą elementów. Jest prawie bez blokady i powinien skalować się lepiej przy wysokiej współbieżności.

Niestety w .NET 4.0 nie było problemu z wydajnością (stałe w 4.5) zobacz http://ayende.com/blog/156097/the-high-cost-of-concurrentbag-in-net-4-0