Ważna uwaga na temat volatile:
- Synchronizacja w Javie jest możliwe za pomocą słów kluczowych, Java
synchronizedi volatilei zamki.
- W Javie nie możemy mieć
synchronizedzmiennej. Używanie synchronizedsłowa kluczowego ze zmienną jest nielegalne i spowoduje błąd kompilacji. Zamiast używać synchronizedzmiennej w Javie, możesz użyć volatilezmiennej java , która poinstruuje wątki JVM, aby odczytały wartość volatilezmiennej z pamięci głównej i nie buforowały jej lokalnie.
- Jeśli zmienna nie jest współużytkowana przez wiele wątków, nie trzeba używać
volatilesłowa kluczowego.
źródło
Przykładowe użycie volatile:
public class Singleton {
private static volatile Singleton _instance; // volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
Instancję tworzymy leniwie w momencie otrzymania pierwszego żądania.
Jeśli nie utworzymy _instancezmiennej, volatileWątek, który tworzy instancję, Singletonnie będzie w stanie komunikować się z drugim wątkiem. Więc jeśli wątek A tworzy instancję Singleton i zaraz po utworzeniu, procesor psuje itp., Wszystkie inne wątki nie będą mogły zobaczyć wartości _instancejako nie zerowej i będą wierzyć, że wciąż jest przypisana zerowa.
Dlaczego to się dzieje? Ponieważ wątki czytnika nie blokują się i dopóki wątek zapisujący nie wyjdzie z synchronizowanego bloku, pamięć nie zostanie zsynchronizowana, a wartość _instancenie zostanie zaktualizowana w pamięci głównej. W przypadku słowa kluczowego Volatile w Javie jest to obsługiwane przez samą Javę i takie aktualizacje będą widoczne dla wszystkich wątków czytelników.
Wniosek : volatilesłowo kluczowe służy również do komunikowania zawartości pamięci między wątkami.
Przykładowe użycie bez lotnych:
public class Singleton{
private static Singleton _instance; //without volatile variable
public static Singleton getInstance(){
if(_instance == null){
synchronized(Singleton.class){
if(_instance == null) _instance = new Singleton();
}
}
return _instance;
}
Powyższy kod nie jest bezpieczny dla wątków. Mimo że ponownie sprawdza wartość instancji w bloku zsynchronizowanym (ze względu na wydajność), kompilator JIT może zmienić porządek kodu bajtowego w taki sposób, aby odwołanie do instancji zostało ustawione przed zakończeniem wykonywania przez konstruktor. Oznacza to, że metoda getInstance () zwraca obiekt, który mógł nie zostać całkowicie zainicjowany. Aby kod był bezpieczny dla wątków, można użyć słowa kluczowego volatile od Java 5 dla zmiennej instancji. Zmienne oznaczone jako lotne są widoczne tylko dla innych wątków, gdy konstruktor obiektu całkowicie zakończy wykonywanie.
Źródło

volatileużycie w Javie :
Szybkie iteratory są zwykle implementowane przy użyciu volatilelicznika na obiekcie listy.
- Gdy lista jest aktualizowana, licznik jest zwiększany.
- Po utworzeniu an
Iteratorbieżąca wartość licznika jest osadzana w Iteratorobiekcie.
- Gdy
Iteratorwykonywana jest operacja, metoda porównuje dwie wartości licznika i wyrzuca a, ConcurrentModificationExceptionjeśli są one różne.
Implementacja iteratorów odpornych na awarie jest zwykle niewielka. Zazwyczaj polegają na właściwościach struktur danych implementacji określonej listy. Nie ma ogólnego wzorca.
volatilektóra pojawiła się wraz z nowym modelem pamięci Java zdefiniowanym w JSR 133: że gdy wątek czytavolatilezmienną, widzi nie tylko wartość ostatnio zapisaną przez inny wątek, ale także wszystkie inne zapisuje do innych zmiennych, które były widoczne w tym drugim wątku w momencievolatilepisania. Zobacz tę odpowiedź i odniesienie .