Czy istnieją ogólne zasady / wytyczne dotyczące tego, co sprawia, że metoda jest bezpieczna dla wątków? Rozumiem, że prawdopodobnie jest milion jednorazowych sytuacji, ale co w ogóle? Czy to takie proste?
- Jeśli metoda uzyskuje dostęp tylko do zmiennych lokalnych, jest bezpieczna wątkowo.
Czy to to? Czy dotyczy to również metod statycznych?
Jedna odpowiedź udzielona przez @Cybis brzmiała:
Zmienne lokalne nie mogą być współużytkowane między wątkami, ponieważ każdy wątek otrzymuje własny stos.
Czy tak jest również w przypadku metod statycznych?
Jeśli do metody zostanie przekazany obiekt referencyjny, czy powoduje to naruszenie bezpieczeństwa wątków? Zrobiłem trochę badań i jest wiele na temat niektórych przypadków, ale miałem nadzieję, że będę w stanie zdefiniować, używając tylko kilku reguł, wskazówek, których należy przestrzegać, aby upewnić się, że metoda jest bezpieczna dla wątków.
Więc wydaje mi się, że moje ostateczne pytanie brzmi: „Czy istnieje krótka lista reguł definiujących metodę bezpieczną dla wątków? Jeśli tak, to jakie?”
EDYCJA
Dokonano tutaj wielu dobrych punktów. Myślę, że prawdziwa odpowiedź na to pytanie brzmi: „Nie ma prostych zasad zapewniających bezpieczeństwo nici”. Chłodny. W porządku. Ale generalnie myślę, że zaakceptowana odpowiedź stanowi dobre, krótkie podsumowanie. Zawsze są wyjątki. Niech tak będzie. Moge z tym zyc.
źródło
Odpowiedzi:
Jeśli metoda (instancja lub statyczna) odwołuje się tylko do zmiennych objętych zakresem tej metody, jest bezpieczna wątkowo, ponieważ każdy wątek ma swój własny stos:
W tym przypadku wiele wątków może wywoływać
ThreadSafeMethod
jednocześnie bez problemu.Dotyczy to również sytuacji, gdy metoda wywołuje inną metodę klasy, która odwołuje się tylko do zmiennych o zasięgu lokalnym:
Jeśli metoda uzyskuje dostęp do właściwości lub pól (stanu obiektu) (instancja lub statyczne), należy użyć blokad, aby upewnić się, że wartości nie są modyfikowane przez inny wątek.
Należy pamiętać, że wszelkie parametry przekazane do metody, które nie są strukturą lub niezmienne, mogą zostać zmutowane przez inny wątek poza zakresem metody.
Aby zapewnić odpowiednią współbieżność, musisz użyć blokowania.
Aby uzyskać więcej informacji, zobacz odwołanie do instrukcji blokady C # i ReadWriterLockSlim .
lock jest najczęściej przydatny do zapewniania funkcjonalności
ReadWriterLockSlim
pojedynczo , jest przydatny, jeśli potrzebujesz wielu czytelników i pojedynczych pisarzy.źródło
private string someValue;
nie jeststatic
więc każda instancja otrzyma oddzielną kopię tej zmiennej. Czy możesz więc wyjaśnić, dlaczego nie jest to bezpieczne dla wątków?Thing
klasy, do której dostęp ma wiele wątkówAbsolutnie nie. Możesz napisać program z tylko jedną zmienną lokalną dostępną z pojedynczego wątku, który nie jest jednak bezpieczny dla wątków:
https://stackoverflow.com/a/8883117/88656
Absolutnie nie.
Absolutnie nie. Cechą wyróżniającą zmienną lokalną jest to, że jest ona widoczna tylko z zakresu lokalnego , a nie to, że jest alokowana w puli tymczasowej . Dostęp do tej samej zmiennej lokalnej z dwóch różnych wątków jest całkowicie legalny i możliwy. Możesz to zrobić za pomocą metod anonimowych, lambd, bloków iteratorów lub metod asynchronicznych.
Absolutnie nie.
Może.
Będziesz musiał nauczyć się żyć z rozczarowaniem. To bardzo trudny temat.
Nie. Jak widać z mojego wcześniejszego przykładu, metoda pusta może nie być bezpieczna dla wątków . Równie dobrze możesz zapytać „czy istnieje krótka lista reguł zapewniających poprawność metody ”. Nie, nie ma. Bezpieczeństwo nici to nic innego jak niezwykle skomplikowany rodzaj poprawności.
Co więcej, fakt, że zadajesz to pytanie, wskazuje na twoje fundamentalne nieporozumienie dotyczące bezpieczeństwa nici. Bezpieczeństwo wątków jest globalną , a nie lokalną właściwością programu. Powodem, dla którego jest to tak trudne, jest to, że musisz mieć pełną wiedzę na temat zachowania wątków całego programu , aby zapewnić jego bezpieczeństwo.
Ponownie spójrz na mój przykład: każda metoda jest trywialna . To sposób, w jaki metody współdziałają ze sobą na poziomie „globalnym”, powoduje impas w programie. Nie możesz spojrzeć na każdą metodę i odznaczyć ją jako „bezpieczną”, a następnie oczekiwać, że cały program jest bezpieczny, tak samo jak nie możesz stwierdzić, że ponieważ Twój dom jest wykonany w 100% z pustaków, to dom jest również nie pusty. Pustka w domu jest ogólną właściwością całości, a nie sumą właściwości jego części.
źródło
class C { public static Func<int> getter; public static Action<int> setter; public static void M() { int x = 0; getter = ()=>x; setter = y=>{x=y;};} }
Zadzwoń do M (), a następnie wywołaj C.getter i C.setter w dwóch różnych wątkach. Zmienna lokalna może być teraz zapisywana i odczytywana w dwóch różnych wątkach, nawet jeśli jest lokalna. Ponownie: cechą definiującą zmienną lokalną jest to, że jest lokalna , a nie to, że znajduje się na stosie wątku .Nie ma sztywnej reguły.
Oto kilka reguł zapewniających bezpieczeństwo wątku kodu w .NET i dlaczego nie są to dobre reguły:
lock
mieć wspólną rzecz. Wszystkie zamki należy wykonać w tej samej kolejności. Dzięki temu wątek kodu będzie bezpieczny, ale będzie niewiarygodnie wolny i równie dobrze możesz nie używać wielu wątków.Nie ma reguły, która zapewnia bezpieczeństwo wątku kodu, jedyne, co możesz zrobić, to upewnić się, że kod będzie działał bez względu na to, ile razy jest aktywnie wykonywany, każdy wątek może zostać przerwany w dowolnym momencie, a każdy wątek jest w własny stan / lokalizację, i to dla każdej funkcji (statycznej lub innej), która uzyskuje dostęp do wspólnych obiektów.
źródło
Musi być zsynchronizowana przy użyciu blokady obiektu, bezstanowej lub niezmiennej.
link: http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
źródło