Czytałem wielowątkowość w Javie i natknąłem się na to
Zmienne lokalne są bezpieczne dla wątków w Javie.
Od tego czasu zastanawiałem się, jak / dlaczego zmienne lokalne są bezpieczne dla wątków.
Czy ktoś może mi dać znać.
Czytałem wielowątkowość w Javie i natknąłem się na to
Zmienne lokalne są bezpieczne dla wątków w Javie.
Od tego czasu zastanawiałem się, jak / dlaczego zmienne lokalne są bezpieczne dla wątków.
Czy ktoś może mi dać znać.
Odpowiedzi:
Kiedy tworzysz wątek, będzie miał utworzony własny stos. Dwa wątki będą miały dwa stosy, a jeden wątek nigdy nie będzie dzielił stosu z innym wątkiem.
Wszystkie zmienne lokalne zdefiniowane w twoim programie zostaną przydzielone w pamięci na stosie (jak skomentował Jatin, pamięć tutaj oznacza wartość odniesienia dla obiektów i wartość dla typów pierwotnych) (Każda metoda wywoływana przez wątek tworzy ramkę stosu na swoim własnym stosie). Jak tylko wykonanie metody zostanie zakończone przez ten wątek, ramka stosu zostanie usunięta.
Na youtube jest świetny wykład profesora Stanforda, który może pomóc w zrozumieniu tej koncepcji.
Zmienne lokalne są przechowywane we własnym stosie każdego wątku. Oznacza to, że zmienne lokalne nigdy nie są współużytkowane między wątkami. Oznacza to również, że wszystkie lokalne zmienne pierwotne są bezpieczne dla wątków.
public void someMethod(){
long threadSafeInt = 0;
threadSafeInt++;
}
Lokalne odniesienia do obiektów są nieco inne. Samo odniesienie nie jest udostępniane. Jednak obiekt, do którego się odwołuje, nie jest przechowywany na stosie lokalnym każdego wątku. Wszystkie obiekty są przechowywane w udostępnionej stercie. Jeśli obiekt utworzony lokalnie nigdy nie ucieknie z metody, w której został utworzony, jest bezpieczny wątkowo. W rzeczywistości możesz również przekazać go innym metodom i obiektom, o ile żadna z tych metod lub obiektów nie udostępnia przekazanego obiektu innym wątkom
Pomyśl o metodach, takich jak definicje funkcjonalności. Gdy dwa wątki uruchamiają tę samą metodę, nie są w żaden sposób powiązane. Każdy z nich utworzy własną wersję każdej zmiennej lokalnej i nie będzie w stanie w żaden sposób współdziałać ze sobą.
Jeśli zmienne nie są lokalne (jak zmienne instancji zdefiniowane poza metodą na poziomie klasy), to są one dołączane do instancji (a nie do pojedynczego uruchomienia metody). W takim przypadku dwa wątki działające tą samą metodą widzą jedną zmienną i nie jest to bezpieczne dla wątków.
Rozważ te dwa przypadki:
public class NotThreadsafe {
int x = 0;
public int incrementX() {
x++;
return x;
}
}
public class Threadsafe {
public int getTwoTimesTwo() {
int x = 1;
x++;
return x*x;
}
}
W pierwszym dwa wątki działające w tej samej instancji programu NotThreadsafe
zobaczą ten sam x. Może to być niebezpieczne, ponieważ wątki próbują zmienić x! W drugim przypadku dwa wątki działające w tej samej instancji programu Threadsafe
będą widzieć zupełnie różne zmienne i nie będą mogły na siebie wpływać.
Każde wywołanie metody ma swoje własne zmienne lokalne i oczywiście wywołanie metody ma miejsce w pojedynczym wątku. Zmienna, która jest aktualizowana tylko przez jeden wątek, jest z natury bezpieczna dla wątków.
Jednak uważnie obserwuj, co dokładnie to oznacza: tylko zapisy do samej zmiennej są bezpieczne dla wątków; wywoływanie metod na obiekcie, do którego się odwołuje, nie jest z natury bezpieczne dla wątków . To samo dotyczy bezpośredniego aktualizowania zmiennych obiektu.
Oprócz innych odpowiedzi, takich jak Nambari.
Chciałbym zaznaczyć, że możesz użyć zmiennej lokalnej w metodzie anonimowej:
Ta metoda może być wywoływana w innych wątkach, które mogą naruszyć bezpieczeństwo wątków, więc java wymusza zadeklarowanie wszystkich zmiennych lokalnych używanych w anonimowych typach jako ostateczne.
Rozważ ten nielegalny kod:
public void nonCompilableMethod() {
int i=0;
for(int t=0; t<100; t++)
{
new Thread(new Runnable() {
public void run() {
i++; //compile error, i must be final:
//Cannot refer to a non-final variable i inside an
//inner class defined in a different method
}
}).start();
}
}
Gdyby Java na to pozwalała (tak jak C # robi to przez „zamknięcia”), zmienna lokalna nie byłaby już wątkowo bezpieczna w każdych okolicznościach. W takim przypadku wartość i
na końcu wszystkich wątków nie jest gwarantowana 100
.
Wątek będzie miał własny stos. Dwa wątki będą miały dwa stosy, a jeden wątek nigdy nie będzie dzielił stosu z innym wątkiem. Zmienne lokalne są przechowywane we własnym stosie każdego wątku. Oznacza to, że zmienne lokalne nigdy nie są współużytkowane między wątkami.
Zasadniczo istnieją cztery typy pamięci masowej w java do przechowywania informacji o klasach i danych:
Obszar metod, sterta, stos JAVA, PC
więc obszar Metody i Sterta są współdzielone przez wszystkie wątki, ale każdy wątek ma własny stos JAVA i komputer, który nie jest współdzielony przez żadne inne wątki.
Każda metoda w java jest jak ramka stosu. tak więc, gdy jedna metoda jest wywoływana przez wątek, ramka stosu jest ładowana do stosu JAVA. Wszystkie zmienne lokalne, które są w tej ramce stosu i stosie powiązanych operandów, nie są współdzielone przez inne. Komputer będzie miał informację o następnej instrukcji do wykonania w kodzie bajtowym metody. więc wszystkie zmienne lokalne są BEZPIECZNE.
@Weston również dał dobrą odpowiedź.
Na stosie wątków są przechowywane tylko zmienne lokalne .
Zmienna lokalna czyli primitive type
(np. Int, long ...) jest przechowywana w tym thread stack
wątku i w rezultacie inny wątek nie ma do niej dostępu.
Zmienna lokalna, która jest reference type
(następcą Object
) zawiera z 2 części - adres (na którym jest przechowywany thread stack
) i obiekt (na którym jest przechowywany heap
)
class MyRunnable implements Runnable() {
public void run() {
method1();
}
void method1() {
int intPrimitive = 1;
method2();
}
void method2() {
MyObject1 myObject1 = new MyObject1();
}
}
class MyObject1 {
MyObject2 myObject2 = new MyObject2();
}
class MyObject2 {
MyObject3 myObject3 = MyObject3.shared;
}
class MyObject3 {
static MyObject3 shared = new MyObject3();
boolean b = false;
}