Zastanawiałem się, czy masz metodę statyczną, która nie jest zsynchronizowana, ale nie modyfikuje żadnych zmiennych statycznych, czy jest bezpieczna wątkowo? A co jeśli metoda tworzy w niej zmienne lokalne? Na przykład, czy poniższy kod jest bezpieczny dla wątków?
public static String[] makeStringArray( String a, String b ){
return new String[]{ a, b };
}
Więc jeśli mam dwa wątki wzywające tę metodę w sposób ciągły i równoczesny, jeden z psami (powiedz „dog niemiecki” i „pies byk”), a drugi z kotami (powiedz „perski” i „syjamski”), czy kiedykolwiek dostanę koty i psy w tej samej tablicy? A może koty i psy nigdy nie będą znajdować się w tym samym inwokacji metody w tym samym czasie?
Odpowiedzi:
Ta metoda jest w 100% bezpieczna dla wątków, nawet gdyby nie była
static
. Problem z bezpieczeństwem wątków pojawia się, gdy musisz udostępniać dane między wątkami - musisz zadbać o atomowość, widoczność itp.Ta metoda działa tylko na parametrach, które znajdują się na stosie i odwołaniach do niezmiennych obiektów na stercie. Stos jest z natury lokalny dla wątku , więc nigdy nie następuje udostępnianie danych.
Niezmienne obiekty (
String
w tym przypadku) są również bezpieczne dla wątków, ponieważ po utworzeniu nie można ich zmienić, a wszystkie wątki mają tę samą wartość. Z drugiej strony, gdyby metoda akceptowała (zmienna)Date
, mógłbyś mieć problem. Dwa wątki mogą jednocześnie modyfikować tę samą instancję obiektu, powodując warunki wyścigu i problemy z widocznością.źródło
Metoda może być niebezpieczna dla wątków tylko wtedy, gdy zmienia stan udostępnienia. Nie ma znaczenia, czy jest statyczny, czy nie.
źródło
Ta funkcja jest całkowicie bezpieczna dla wątków.
Jeśli się nad tym zastanowić ... załóżmy, co by się stało, gdyby było inaczej. Każda zwykła funkcja miałaby problemy z wątkami, gdyby nie była zsynchronizowana, więc wszystkie funkcje API w JDK musiałyby być zsynchronizowane, ponieważ potencjalnie mogłyby być wywoływane przez wiele wątków. A ponieważ przez większość czasu aplikacja korzysta z jakiegoś interfejsu API, aplikacje wielowątkowe byłyby praktycznie niemożliwe.
To zbyt śmieszne, aby o tym myśleć, więc tylko dla Ciebie: metody nie są bezpieczne dla wątków, jeśli istnieje wyraźny powód, dla którego mogą wystąpić problemy. Staraj się zawsze myśleć o tym, co by było, gdyby w mojej funkcji było wiele wątków, a co, gdybyś miał debuger krokowy i krok po kroku przesuwał pierwszy ... potem drugi wątek ... może znowu drugi ... czy byłyby problemy? Jeśli znajdziesz, nie jest bezpieczny wątkowo.
Należy również pamiętać, że większość klas Java 1.5 Collection nie jest bezpieczna wątkowo, z wyjątkiem tych, w których jest to określone, takich jak ConcurrentHashMap.
A jeśli naprawdę chcesz się w to zagłębić, przyjrzyj się uważnie słowu kluczowemu „volatile” i WSZYSTKIM jego skutkom ubocznym. Przyjrzyj się klasom Semaphore () i Lock () oraz ich przyjaciołom w java.util.Concurrent. Przeczytaj całą dokumentację API dotyczącą klas. Warto się uczyć i satysfakcjonować.
Przepraszam za tę zbyt rozbudowaną odpowiedź.
źródło
Użyj
static
słowa kluczowego ze zsynchronizowanymi metodami statycznymi, aby zmodyfikować dane statyczne współdzielone między wątkami. Za pomocąstatic
słowa kluczowego wszystkie utworzone wątki będą walczyć o jedną wersję metody.Użycie
volatile
słowa kluczowego wraz z metodami zsynchronizowanych wystąpień zagwarantuje, że każdy wątek będzie miał własną kopię udostępnionych danych i żadne operacje odczytu / zapisu nie będą wyciekać między wątkami.źródło
Niezmienne obiekty ciągów to kolejny powód powyższego scenariusza bezpiecznego dla wątków. Zamiast tego, jeśli używane są zmienne obiekty (powiedzmy makeMutableArray ..), z pewnością zostanie przerwane bezpieczeństwo wątków.
źródło