volatile to modyfikator zmiennej, który zapewnia widoczność zmian tej zmiennej dla wszystkich wątków. Jeśli zmienna jest zadeklarowana jako volatile, to jej odczyt i zapis odbywają się bezpośrednio z pamięci głównej, omijając lokalne pamięci podręczne wątków. Zapobiega to lokalnemu buforowaniu wartości w wątku.
synchronized to słowo kluczowe, które zapewnia nie tylko widoczność, ale także wzajemne wykluczenie (mutual exclusion): tylko jeden wątek może wykonywać zsynchronizowany blok w danym momencie dla danego obiektu.
Zmiennych volatile należy używać dla prostych flag i liczników, jeśli:
Przykład użycia zmiennej volatile:
class Flag { private volatile boolean running = true; public void stop() { running = false; } public void loop() { while (running) { // ... } } }
Czy można używać volatile do zapewnienia atomowości inkrementacji zmiennej?
Odpowiedź:
Nie, volatile nie zapewnia atomowości operacji. Na przykład, counter++ nie jest operacją atomową, nawet jeśli counter jest zadeklarowany jako volatile, ponieważ operacja obejmuje odczyt, modyfikację i zapis (wiele działań), które mogą być przerwane przez inny wątek. Atomowość zapewnia synchronizacja lub klasy z pakietu java.util.concurrent.atomic.
Przykład:
class Counter { private volatile int count = 0; public void increment() { count++; // NIE atomowa operacja! } }
Historia
W projekcie sklepu internetowego flaga zakończenia wątku przetwarzania zamówień była implementowana bez volatile. W wyniku tego jeden z wątków „zawiesił się” w nieskończonej pętli, ponieważ nie widział zmiany zmiennej dokonanej przez inny wątek. Diagnostyka zajęła kilka dni.
Historia
W systemie finansowym programista użył volatile int do licznika operacji. W szczytowych obciążeniach liczba operacji zaczynała „znikać”. Przyczyna - utrata atomowości podczas złożonych operacji inkrementacji.
Historia
Programiści pomylili volatile i synchronized, próbując użyć volatile do zapewnienia wzajemnego wykluczenia dostępu do sekcji krytycznych, co doprowadziło do wyścigu danych i trudnych do wychwycenia błędów w aplikacji wielowątkowej.