C #: Co się stanie, jeśli metoda statyczna jest wywoływana z wielu wątków?


94

W mojej aplikacji mam metodę statyczną, która jest wywoływana z wielu wątków w tym samym czasie. Czy istnieje niebezpieczeństwo pomylenia moich danych?

W mojej pierwszej próbie metoda nie była statyczna i tworzyłem wiele instancji tej klasy. W takim przypadku moje dane zostały w jakiś sposób pomieszane. Nie jestem pewien, jak to się dzieje, ponieważ zdarza się to tylko czasami. Nadal debuguję. Ale teraz metoda jest statyczna i jak dotąd nie mam żadnych problemów. Może to tylko szczęście. Nie wiem na pewno.


Odpowiedzi:


98

Zmienne zadeklarowane wewnątrz metod (z możliwym wyjątkiem „ przechwyconych ” zmiennych) są izolowane, więc nie wystąpią żadne nieodłączne problemy; jeśli jednak Twoja metoda statyczna uzyskuje dostęp do dowolnego stanu wspólnego, wszystkie zakłady są wyłączone.

Przykłady stanu współdzielonego to:

  • pola statyczne
  • obiekty dostępne ze wspólnej pamięci podręcznej (niezserializowane)
  • dane uzyskane za pomocą parametrów wejściowych (i stanu tych obiektów), jeśli jest możliwe, że wiele wątków dotyka tego samego obiektu (ów)

Jeśli masz wspólny stan, musisz:

  • uważaj, aby nie mutować stanu, gdy można go udostępnić (lepiej: użyj niezmiennych obiektów do reprezentowania stanu i zrób migawkę stanu w zmiennej lokalnej - tj. zamiast odwoływać się whatever.SomeDatawielokrotnie, wczytujesz whatever.SomeData raz do zmiennej lokalnej, a następnie po prostu użyj zmiennej - pamiętaj, że pomaga to tylko w przypadku niezmiennego stanu!)
  • zsynchronizować dostęp do danych (wszystkie wątki muszą się zsynchronizować) - wzajemnie wykluczające się lub (bardziej szczegółowe) czytnik / pisarz

1
@Diego - czy ten komentarz jest przeznaczony dla mnie, czy dla @Holli?
Marc Gravell

Do Holli, żeby dodać kilka praktycznych informacji do twojej odpowiedzi.
Diego Pereyra

1
@Marc Nie do końca zgadzam się z tym, że „Zmienne zadeklarowane wewnątrz metod (z możliwym wyjątkiem„ przechwyconych ”zmiennych) są izolowane”. Rozważ uchwyt pliku zadeklarowany w metodzie statycznej. Wtedy jeden nić może uzyskać dostęp do uchwytu, gdy inny nić go używa. Doprowadzi to do nieoczekiwanego zachowania. Czy też twoja „przechwycona” zmienna oznaczała również „uchwyt pliku”.
prabhakaran

9
@prabhakaran Jeśli uchwyt pliku jest zmienną metody, jest ograniczony tylko do tego wywołującego. Każdy inny rozmówca będzie rozmawiał z inną zmienną (zmienne metody są przypisane do wywołania). Teraz dostęp do pliku źródłowego jest osobnym problemem, ale nie jest to związane z językiem C # ani .NET. Jeśli uchwyt nie jest współdzielony, można by się spodziewać jakiegoś mutexu / blokady, jeśli taki scenariusz jest prawdopodobny.
Marc Gravell

29

Tak, to tylko szczęście. ;)

Nie ma znaczenia, czy metoda jest statyczna, czy nie, ważne jest, czy dane są statyczne, czy nie.

Jeśli każdy wątek ma własne, oddzielne wystąpienie klasy z własnym zestawem danych, nie ma ryzyka pomieszania danych. Jeśli dane są statyczne, istnieje tylko jeden zestaw danych, a wszystkie wątki współużytkują te same dane, więc nie ma sposobu, aby ich nie pomieszać.

Kiedy dane w oddzielnych instancjach nadal się mieszają, najprawdopodobniej nie są one tak naprawdę oddzielne.


7
Uwielbiałem tę linię - It doesn't matter if the method is static or not, what matters is if the data is static or not. Dodam, że zmienne lokalne zadeklarowane w ramach metody statycznej nie stanowią tej części danych, o którą w danym scenariuszu musimy się przejmować.
RBT

świetna odpowiedź. Bardzo pomogło.
Fraktal

15

Metody statyczne powinny być odpowiednie dla wielu wątków.

Z drugiej strony dane statyczne mogą powodować problem, ponieważ próby uzyskania dostępu do tych samych danych z różnych wątków muszą być kontrolowane, aby zapewnić, że tylko jeden wątek na raz odczytuje lub zapisuje dane.


2

2
czytanie jest w porządku, aby odbywać się jednocześnie, ale jednoczesne czytanie ORAZ pisanie doprowadzi do nieoczekiwanego zachowania
Freestyle076

10

MSDN zawsze mówi:

Wszystkie publiczne statyczne elementy członkowskie tego typu (udostępnione w języku Visual Basic) są bezpieczne wątkowo. Nie ma gwarancji, że żadne elementy członkowskie instancji będą bezpieczne dla wątków.

Edycja: Jak mówią ludzie tutaj, nie zawsze tak jest i wyraźnie dotyczy to klas zaprojektowanych w ten sposób w BCL, a nie klas utworzonych przez użytkowników, gdzie to nie ma zastosowania.


3
Uff! Wreszcie zrozumiałem znaczenie tej notatki, która tak często znajduje się w dokumentacji MSDN. Zasadniczo, kiedy MS projektuje metodę statyczną (gdzie ta notatka jest publikowana) w BCL, nie ma dostępu do żadnej zmiennej / elementu członkowskiego / stanu, który jest poza zakresem tej metody. Opierają się one całkowicie na zmiennych lokalnych w zakresie metody tylko w celu implementacji logiki tej metody. Bardzo się cieszę, że się podzieliłeś.
RBT

@Marcote, czy nie jest odwrotnie? Członkowie instancji są bezpieczni, ponieważ jest jedna na instancję. Jednak statyczne elementy członkowskie nie są bezpieczne dla wątków, ponieważ są współużytkowane przez wszystkie wystąpienia tej klasy? quora.com/…
Fraktal

1
to zależy. Nigdy nie traktowałbym domyślnie elementu instancji jako bezpiecznego. Właśnie dlatego cały zestaw bibliotek i między innymi unikanie uszkodzenia danych.
Marcote

1
okej, dzięki @Marcote. Powoli dochodzę do wniosku, że muszę się wiele nauczyć.
Fractal
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.