Пока циклы не заканчиваются, когда условие выполнено

Насколько я понимаю, следующий код должен нормально завершаться как условие stopRunning = true; встретил

Однако, когда я запускаю эту программу, она печатает только Last line of Main(), Start Method ended никогда не печатается, поскольку цикл while никогда не завершается.

 public class Test {
     private static boolean stopRunning = false;
     public static void main(String[] args) throws Exception {
        new Thread(new Runnable() {

            @Override
            public void run() {
                start();
            }

        }).start();

        Thread.sleep(100);
        stopRunning = true;
        System.out.println("Last line of Main()");
    }
    public static void start() {
        while (!stopRunning) {

        }
        System.out.println("Start Method ended.");
    }
}

Пожалуйста, помогите мне понять это поведение.

3 ответа

Изменение флага на volatile с

private static volatile boolean stopRunning = false;

будет означать, что другие потоки видят изменение немедленно (из основной памяти вместо кэша), и код выполняется так, как вы ожидаете. Как volatile относится к модели памяти Java, объясняется, например, в этом руководстве.

Как сказал Мик, вы должны использовать ключевое слово volatile для синхронизации вашей переменной, поэтому при изменении новое значение записывается непосредственно обратно в память, и ваш код будет работать как положено.

Имейте в виду (также указано в статье, с которой связан Мик), что volatile не гарантирует, что можно избежать условий гонки, поэтому, если два разных потока будут читать вашу переменную, небезопасно, что они оба читают одно и то же значение (несмотря на то, что все читается из памяти и на смену прямо отписался)

Как указано в предыдущих ответах:

  1. Как сказал Майк - в run() вы должны использовать Test.start() или переименовать метод. Начало, которое вы вызываете, является методом запуска потока.
  2. Также, как заявил Мик, установка stopRunning как volatile должна помочь. Причина, по которой он должен работать, заключается в том, что он удалит кэширование переменной в памяти потока и получит / установит непосредственно из памяти.
Другие вопросы по тегам