Потоки и локальный кэш
Встретился пример, показывающий работу ключевого слова volatile:
public class VolatileDemo {
public static void main(String[] args) {
new VolatileDemo().start();
}
//----------------------------------------------
private boolean btExit = false; //без volatile
// запуск потоков
public void start() {
new Thread(gui).start();
System.out.println("gui thread started");
new Thread(game).start();
System.out.println("game thread started");
}
// поток для интерфейса
Runnable gui = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000); // типа пользователь общается с GUI и выходит из игры
} catch (InterruptedException ignored) {}
btExit = true; // поток game не видит это изменение без volatile
System.out.println("gui thread finished");
}
};
// поток для игры
Runnable game = new Runnable() {
@Override
public void run() {
long count = 0;
while (!btExit) {
// без volatile этот цикл крутится бесконечно
count++;
// если раскомментировать строку ниже то цикл завершится!!!
// System.out.println("loop ended without volatile!");
}
System.out.println("game thread finished");
}
};
}
Запускаем потоки, поток gui отрабатывает и изменяет переменную btExit на true, поток game изменение переменной btExit не видит и цикл уходит в вечность.
Как я понял потоки считали себе в локальный кэш переменную btExit и дальнейшие операции чтения/записи проводили из своего локального кэша и у каждого потока было свое значение переменной.
Ключевое слово volatile может эту ситуацию исправить, потоки будут работать с актуальным значением переменной в основной памяти.
Вопрос: если я не применяя volatile к переменной btExit в цикле потока game выведу на печать что-нибудь, либо вызову Thread.sleep() и т.п., то завершение работы потока будет аналогичной с применением volatile(он завершится при btExit = true), почему?