2012-12-03 10 views
16

Niedawno słyszałem w rozmowie, że zapis na lotny wyzwala barierę pamięci dla każdej zmiennej, do której wątek został napisany. Czy to naprawdę prawda? Z JLS wydaje się, że tylko zmienna, o którą chodzi, zostaje przepłukana, ale nie inna. Czy ktoś wie, co jest właściwie poprawne? Czy można wskazać konkretną lokalizację w JLS?Jest to zapis na niestabilną barierę pamięci w Javie

+1

Moja interpretacja JLS zgadza się z twoją. – NPE

+1

możliwy duplikat [Zmiennych zmiennych i innych zmiennych] (http://stackoverflow.com/questions/12438464/volatile-variables-and-other-variables) – assylias

+0

Jak wyjaśnia odpowiedź, to nie tylko zmienna, która została zadeklarowana jako zmienna, ale wszystkie zapisy, które miały miejsce przed niestabilnym zapisem. – sjlee

Odpowiedz

1

Odniesienie do Volatile variables and other variables była poprawna. Nie zdawałem sobie sprawy, że przechodniość zdarzeń występujących wcześniej jest czymś, co musi zostać wdrożone przez VM, a nie czymś, co wynika z definicji. Nadal jestem zdziwiony, dlaczego coś o tak daleko idących konsekwencjach nie jest jasno określone, ale w rzeczywistości wynika z jakiejś definicji. Owinąć go: Załóżmy, że masz 4 działań tak:.

thread1  thread2 
a1 
a2 
       a3 
       a4 

gdzie a2 to napisz do lotnym zmiennej v i A3 jest odczytywana z samego lotnych zmiennej v Wynika z osoby zaliczane dzieje -przedtem (hb) to hb (a1, a2) i hb (a3, a4). Również dla lotnych mamy hb (a2, a3). Wynika to teraz z wymaganej przechodniości hb, która hb (a1, a3). Zatem zapis i późniejsze odczytanie zmiennej lotnej v działa jako bariera pamięci.

16

Tak, zainicjuje barierę. Możesz przeczytać więcej here. Istnieją 4 typy, LoadLoad LoadStore StoreStore StoreLoad.

Jeśli chodzi o Twoje pytanie

Z JLS, wydaje się, że tylko dana zmienna zostaje przepłukany na zewnątrz, ale nie innych. Czy ktoś wie, co jest właściwie poprawne?

Wszystkie zapisy, które wystąpiły przed lotnym magazynem, są widoczne w innych wątkach z predykatem, że inne wątki wczytują ten nowy magazyn. Jednak zapisuje, że występuje, zanim lotne obciążenie może lub nie może być widziane przez inne wątki, jeśli nie załadują nowej wartości.

praktycznego przykładu

volatile int a =0; 
int b = 0; 

Thread-1 
b = 10; 
a = 3; 

Thread-2 
if(a == 0){ 
    // b can b 10 or 0 
} 
if(a == 3){ 
    // b is guaranteed to be 10 (according to the JMM) 
} 
+1

+1 * "z predykatem, że inne wątki wczytują ten nowy sklep" * – assylias

+4

Myślę, że twój przykład jest błędny. Wątek-2 nie musi porównywać "a" do 3, aby zobaczyć nową wartość "b", wystarczy przeczytać "a". Tak więc zaraz po pierwszej linii Gwint-2 gwarantuje, że "b" będzie równe 10 (we wszystkich gałęziach). Jednak trzeci wątek, który nigdy nie czyta "a", nie gwarantuje nowej wartości "b". –

+11

@PhilippWendler Myślę, że chodziło o to, że jeśli a == 0, zapis 'a = 3' jeszcze się nie wydarzył, a b może być dowolne, w tym 10. jeśli a == 3, wystąpił zapis' a = 3' i masz gwarancję, że b == 10. – assylias