Ключевое слово volatile
Ключевое слово volatile применяется к полям класса
и гарантирует, что все потоки будут видеть
самое последнее записанное значение этой переменной.
Без volatile каждый поток может кэшировать
значение переменной в своей локальной памяти
и работать со устаревшей копией. Ключевое слово
volatile заставляет поток при каждом чтении
обращаться к основной памяти, а при каждой записи -
немедленно сбрасывать значение в основную память.
Важно понимать, что volatile обеспечивает
только видимость и запрет переупорядочивания,
но не атомарность составных операций, таких как
i++.
Синтаксис
volatile тип имяПеременной;
Пример
Давайте рассмотрим классический пример, в котором
без volatile поток может никогда не увидеть
изменение флага и зависнуть в бесконечном цикле.
С volatile поток корректно завершит работу:
public class Main
{
static volatile boolean flag = false;
public static void main(String[] args) throws InterruptedException
{
Thread worker = new Thread(() -> {
while (!flag)
{
// waiting for flag to become true
}
System.out.println("Worker stopped");
});
worker.start();
Thread.sleep(100);
flag = true;
System.out.println("Flag set to true");
worker.join();
}
}
Результат выполнения кода:
"Flag set to true"
"Worker stopped"
Пример
Давайте убедимся, что volatile не обеспечивает
атомарность. Два потока инкрементируют одну и ту же
переменную, и итоговое значение может оказаться
меньше ожидаемого:
public class Main
{
static volatile int counter = 0;
public static void main(String[] args) throws InterruptedException
{
Runnable task = () -> {
for (int i = 0; i < 10000; i++)
{
counter++;
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter);
}
}
Результат выполнения кода может быть, например, таким:
15342
Смотрите также
-
ключевое слово
synchronized,
которое обеспечивает и видимость, и атомарность -
класс
AtomicInteger,
который даёт атомарные операции над числом -
класс
Thread,
который представляет поток выполнения -
метод
join,
который ожидает завершения потока