. NET - blokowanie słownika vs. ConcurrentDictionary

Nie mogłem znaleźć wystarczająco dużo informacji o typach ConcurrentDictionary, więc pomyślałem, że zapytam o to tutaj.

Obecnie używam Dictionary do przechowywania wszystkich użytkowników, do których dostęp jest stale uzyskiwany przez wiele wątków (z puli wątków, więc nie ma dokładnej liczby wątków), i ma zsynchronizowany dostęp.

Niedawno dowiedziałem się, że w.NET 4.0 istnieje zestaw kolekcji bezpiecznych dla wątków i wydaje się to być bardzo przyjemne. Zastanawiałem się, jaka byłaby opcja "bardziej efektywna i łatwiejsza w zarządzaniu" , ponieważ mieć opcję pomiędzy zwykłym {[1] } z dostępem synchronicznym, lub mieć ConcurrentDictionary, który jest już bezpieczny dla wątku.

Nawiązanie do. NET 4.0ConcurrentDictionary

Author: ulrichb, 2009-12-23

8 answers

Zbiór bezpieczny dla wątków vs. zbiór Nie-threadsafe może być rozpatrywany w inny sposób.

Rozważmy sklep bez recepcjonistki, z wyjątkiem kasy. Masz mnóstwo problemów, jeśli ludzie nie postępują odpowiedzialnie. Na przykład, powiedzmy, że klient bierze puszkę z piramidy-puszki podczas gdy urzędnik buduje piramidę, całe piekło wybuchnie. Albo, co jeśli dwóch klientów sięga po ten sam przedmiot w tym samym czasie, kto wygrywa? Będzie walka? To jest kolekcja bez wątków. Jest wiele sposobów na uniknięcie problemów, ale wszystkie one wymagają pewnego rodzaju blokady lub raczej wyraźnego dostępu w jakiś sposób. Z drugiej strony, rozważ sklep z urzędnikiem przy biurku, a możesz robić zakupy tylko przez niego. Stajesz w kolejce i prosisz go o przedmiot, on ci go przynosi, a Ty wypadasz z kolejki. Jeśli potrzebujesz kilku przedmiotów, możesz odebrać tylko tyle przedmiotów w każdej podróży w obie strony, ile pamiętasz, ale musisz uważać, aby unikaj zaczepiania urzędnika, to rozwścieczy innych klientów w kolejce za tobą. Zastanów się nad tym. W sklepie z jednym sprzedawcą, co jeśli dojdziesz aż do przodu linii i zapytasz sprzedawcę "czy masz papier toaletowy", a on powie "Tak", a potem pójdziesz "Ok, odezwę się, gdy będę wiedział, ile potrzebuję", a następnie do czasu, gdy wrócisz na początek linii, sklep może być oczywiście wyprzedany. Ten scenariusz nie jest zapobiegany przez threadsafe kolekcja.

Kolekcja threadsafe gwarantuje, że jej wewnętrzne struktury danych są ważne przez cały czas, nawet jeśli są dostępne z wielu wątków.

Zbiór bez wątków nie posiada takich gwarancji. Na przykład, jeśli dodasz coś do drzewa binarnego w jednym wątku, podczas gdy inny wątek jest zajęty równoważeniem drzewa, nie ma gwarancji, że element zostanie dodany, a nawet że drzewo będzie nadal ważne, może być uszkodzone poza nadzieją.

A kolekcja threadsafe nie gwarantuje jednak, że sekwencyjne operacje na wątku działają na tej samej "migawce" jego wewnętrznej struktury danych, co oznacza, że jeśli masz kod taki jak ten: {]}

if (tree.Count > 0)
    Debug.WriteLine(tree.First().ToString());

Możesz otrzymać wyjątek NullReferenceException, ponieważ inbetween tree.Count i tree.First(), inny wątek wyczyścił pozostałe węzły w drzewie, co oznacza, że First() zwróci null.

W tym scenariuszu musisz sprawdzić, czy dana kolekcja ma bezpieczny sposób na uzyskanie co chcesz, być może trzeba przepisać powyższy kod, lub może trzeba zablokować.

 130
Author: Lasse Vågsæther Karlsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-27 17:23:37

Nadal musisz być bardzo ostrożny, gdy używasz kolekcji thread-safe, ponieważ thread-safe nie oznacza, że możesz ignorować wszystkie problemy związane z wątkiem. Gdy zbiór reklamuje się jako bezpieczny dla wątków, zwykle oznacza to, że pozostaje w stanie spójnym, nawet gdy wiele wątków czyta i pisze jednocześnie. Nie oznacza to jednak, że pojedynczy wątek zobaczy "logiczną" sekwencję wyników, jeśli wywoła wiele metod.

Na przykład, jeśli najpierw sprawdzisz czy klucz istnieje i następnie uzyskaj wartość odpowiadającą kluczowi, ten klucz może już nie istnieć nawet w wersji współbieżnej(ponieważ inny wątek mógł usunąć klucz). W tym przypadku nadal musisz użyć blokady (lub lepiej: połącz oba wywołania używając TryGetValue ).

Więc używaj ich, ale nie myśl, że to daje Ci wolną przepustkę do ignorowania wszystkich problemów z współbieżnością. Nadal musisz być ostrożny.

 55
Author: Mark Byers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 21:21:07

Wewnętrznie ConcurrentDictionary używa oddzielnej blokady dla każdego zasobnika skrótu. Tak długo, jak używasz tylko metod Add/TryGetValue i podobnych, które działają na pojedynczych wpisach, słownik będzie działał jako prawie wolna od blokad struktura danych z odpowiednią korzyścią sweet performance. OTOH metody wyliczania (w tym właściwość Count) blokują wszystkie wiadra naraz i dlatego są gorsze niż zsynchronizowany Słownik pod względem wydajności.

Powiedziałbym, po prostu użyj ConcurrentDictionary.

 32
Author: Stefan Dragnev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-26 10:17:19

Czy widziałeś Reactive Extensions dla. Net 3. 5sp1. Według Jona Skeeta, backportowali pakiet równoległych rozszerzeń i współbieżnych struktur danych dla .Net3.5 sp1.

Istnieje zestaw próbek dla. Net 4 Beta 2, który opisuje dość szczegółowo, jak z nich korzystać, równoległe rozszerzenia.

Właśnie spędziłem ostatni tydzień testując ConcurrentDictionary używając 32 wątków do wykonywania I / O. wydaje się działać zgodnie z reklamą, co byłoby / align = "left" /

Edit:. NET 4 ConcurrentDictionary i patterns.

Microsoft wydał pdf o nazwie Patterns of parallel Programming. Jego naprawdę warto pobrać, Jak to opisano w naprawdę ładne szczegóły właściwe wzorce do wykorzystania dla. Net 4 równoległych rozszerzeń i anty wzorce, aby uniknąć. tutaj jest.

 14
Author: scope_creep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-24 14:12:05

Myślę, żeMetoda GetOrAdd jest dokładnie tym, czego potrzebuje większość scenariuszy wielowątkowych.

 13
Author: Konstantin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-27 16:36:53

Zasadniczo chcesz przejść z nowym ConcurrentDictionary. Od razu po wyjęciu z pudełka musisz napisać mniej kodu, aby stworzyć bezpieczne programy.

 5
Author: ChaosPandion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 21:10:43

Użyliśmy ConcurrentDictionary dla buforowanej kolekcji, która jest ponownie wypełniana co 1 godzinę, a następnie odczytywana przez wiele wątków klienta, podobnie do rozwiązania dla Czy ten przykładowy wątek jest bezpieczny?Pytanie.

Okazało się, że zmiana go na ReadOnlyDictionary poprawiła ogólną wydajność.

 1
Author: Michael Freidgeim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:20

Jest dobry kurs o kolekcjach współbieżnych w c# pod maską: Pluralsight concurrent collections

Znajdziesz tam wszystkie ciekawe informacje.

 0
Author: DmitryZyr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-15 15:21:07