2012-02-09 19 views
7

Powiel możliwe:
Are C# arrays thread safe?Wiele wątków z dostępem samej tablicy wielowymiarowej

I zostały programowania C# przez 10 miesięcy. Teraz uczę się wielowątkowości i wydaje mi się, że działa miło. Muszę wielowymiarowej tablicy wymiar jak

string[,] test = new string[5, 13]; 

mam nici wywoływanie metod, które kończą się zapisywanie ich wyjść różnych współrzędnych wewnątrz tablicy powyżej. bez żadnego wątku zapisującego do tej samej lokalizacji co inny wątek.

Więc thread1 może napisać do test[1,10] ale żaden inny wątek nie będzie kiedykolwiek napisać do test[1,10]

Moje pytanie brzmi: czytałem o użyciu blokad na obiektach takich jak mojej tablicy, muszę się martwić w ogóle o zamkach mimo że moje wątki mogą mieć dostęp do tablicy testowej w tym samym czasie, ale nigdy nie zapisują do tych samych współrzędnych (położenie pamięci)?

Do tej pory nie miałem żadnych problemów z testowaniem, ale jeśli ktoś bardziej doświadczony niż ja wie, że mogę go wydać, zajrzę się blokadami użytkowania.

+1

Nie, nie potrzebujesz zamków w wyjaśnianym scenariuszu. Ale zakładam, że czytasz dane w pewnym momencie? Czy czekasz, aż wszystkie wątki skończą się przed rozpoczęciem czytania? – Douglas

+1

Jeśli nie używasz blokad, zaleca się wprowadzenie blokady pamięci (przez wywołanie 'Thread.MemoryBarrier()') przed rozpoczęciem czytania, aby upewnić się, że wszystkie wątki mają dostęp do "świeżych" danych. [Nonblocking Synchronization] (http://www.albahari.com/threading/part4.aspx) ma świetne wyjaśnienie na temat tej koncepcji. – Douglas

+0

dzięki, wątki są tworzone z jednego głównego wątku, piszą tylko dane do tablicy, a gdy wszystko się skończy, RunWorkerCompleted poza głównym wątkiem, odczytuje tablicę. więc myślę, że jestem bezpieczny, dzięki za wyjaśnienie. –

Odpowiedz

7

Jeśli możesz upewnić się, że żadne dwa wątki nigdy nie spróbują odczytać lub zapisać do tego samego elementu, nie musisz wykonywać żadnego blokowania, a jeśli dodasz blokowanie, spowolnisz swój kod.

Powinieneś jednak poświęcić trochę czasu na dodanie komentarzy, aby wyjaśnić, że (i prawdopodobnie dlaczego) żadne wątki nie mają dostępu do tych samych elementów, aby uniknąć przyszłych problemów, które Jim Fell wspomniał w swojej odpowiedzi.

Aktualizacja: Wiele innych plakatów nadal sugeruje, że blokowanie może być używane jedynie jako zabezpieczenie przed błędami przyszłych deweloperów. W tym celu to naprawdę zależy od twojej aplikacji. Jeśli wydajność naprawdę nie stanowi większego problemu, to z pewnością zsynchronizuj dostęp do elementów.

Jednak przez większość czasu, w którym wiele wątków ma dostęp do pojedynczej tablicy, powodem istnienia wielu wątków jest równoległe przetwarzanie dużych ilości danych, których wydajność jest poważnym problemem. Jeśli nie było to powodem do niepokoju, możesz po prostu użyć pojedynczego wątku i być o wiele bardziej spokojnym, ponieważ nie jest on zniekształcony przez innych. Przy tak dużej mocy obliczeniowej poleganie na blokadzie (w różnych formach) jest z zasady minimalizowane, gdy tylko jest to możliwe. Synchronizacja poprzez rozdzielenie danych (czyli zapobieganie ich odczytywaniu/zapisywaniu w tych samych lokalizacjach pamięci) jest o wiele lepsza od używania zamków, kiedy jest to wykonalne.

0

Powinieneś używać instrukcji blokujących, aby upewnić się, że obiekt danych jest wątkowo bezpieczny. To może działać teraz, ale później (szczególnie, gdy/jeśli kod zostanie zaktualizowany) ty (lub twój zamiennik) może natknąć się na nieuchwytne błędy wyścigowe lub błędy związane z uszkodzeniem danych. Check out this article on the MSDN website. Ma ładny przykład, jak używać instrukcji blokujących.

1

Jedną z rzeczy, na którą należy zwrócić uwagę, jest to, że podczas testowania za pomocą jednego procesora lokalnego wszystko może działać poprawnie, ale zaraz po uruchomieniu na procesorze wielordzeniowym występują problemy z wątkami trafiającymi na wspólny kawałek pamięć w tym samym czasie.

Po to, aby być bezpiecznym, jeśli te dwa wątki modyfikują bezpośrednio macierz, musisz zaimplementować system blokowania. This answer in StackOverflow ma dobry przykład blokowania.

-1

Zamki służą tylko do uniemożliwienia równoczesnego dostępu. Więc jeśli zagwarantujesz to w inny sposób, nie potrzebujesz żadnych zamków.

P.S. Przypuszczam, że przypisałeś każdy wątek do każdego elementu tablicy, prawda?

+4

Jednoczesny dostęp to tylko problem, jeśli jednoczesne operacje to * mutowanie * i * brak atomu *. Ale zamki robią więcej, niż operacje nieatomowe w operacje atomowe; wprowadzają także * pełnozakresowe bariery pamięci *. Przypuśćmy, że autor kodu sprytnie gwarantuje, że żadne dwa nieatomowe odczyty/zapisy pamięci nie będą przeplatane; to świetnie, ale może to być niewystarczające. ** Takie działanie nie gwarantuje, że dwa wątki mają * spójny * widok wszystkich mutacji do wszystkich danych **. –

+0

Powiedział, że każdy wątek działa z własnym elementem tablicy. Kolejność nie ma tutaj znaczenia. – Dims

+2

Nie podążasz za moją myślą. Przypuśćmy, że wątek Alpha zapisuje 123 w miejscu tablicy 2. Przypuśćmy, że wątek Bravo jest gwarantowany, że nie odczyta położenia 2 dopóki nie zostanie zrobiona mutacja za pomocą jakiegoś nieblokującego rozwiązania. Jaka jest gwarancja, że ​​gdy wątek Bravo odczytuje położenie 2, znajdzie 123 w tej lokalizacji? Absolutnie nic! Wątek Bravo może działać na innym procesorze niż wątek Alpha, a ** procesor Bravo może mieć buforowaną stronę pamięci tablicy. ** Co zmusza procesor Bravo do unieważnienia pamięci podręcznej? *Nic*. –

Powiązane problemy