Потоки и локальный кэш

Встретился пример, показывающий работу ключевого слова 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), почему?


Ответы (0 шт):