вызов сна перезагрузит значения, кэшированные в регистрах в Java isters - PullRequest
1 голос
/ 10 марта 2019

В спецификации Java 17.3 Sleep and Yield

17.3 Sleep and Yield

Thread.sleep приводит к тому, что текущий выполняющийся поток переходит в спящий режим (временно прекращает выполнение) на указанную продолжительность, субъектк точности и точности системных таймеров и планировщиков.Поток не теряет права собственности ни на какие мониторы, и возобновление выполнения будет зависеть от планирования и доступности процессоров для выполнения потока.

Важно отметить, что ни Thread.sleep, ни Thread.yieldиметь любую семантику синхронизации.В частности, компилятору не нужно сбрасывать записи, кэшированные в регистрах, в общую память перед вызовом Thread.sleep или Thread.yield, а также компилятору не нужно перезагружать значения, кэшированные в регистрах, после вызова Thread.sleep или Thread..yield.

Например, в следующем (неработающем) фрагменте кода предположим, что this.done является энергонезависимым логическим полем:

while (!this.done)
    Thread.sleep(1000);

Компиляторсвободно читать поле this.done только один раз и повторно использовать кэшированное значение при каждом выполнении цикла.Это будет означать, что цикл никогда не завершится, даже если другой поток изменил значение this.done

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

public class TestDemo {

    private  static boolean  keepRunning = true;

    public static void main(String[] args)  throws Exception {
        new Thread(
            ()->{
                while (keepRunning){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {

                    }
                }
                System.out.println("loop terminates");
            }
        ).start();
        Thread.sleep(1000);
        keepRunning = false;
        System.out.println("keepRunning is false now");
    }
}

Результат:

что-то не так с кодом в спецификации Java 17.3?

почему поле keepRunning будетперезагрузил после звонка спать?

    C:\Users\LuoYY\Desktop>javac TestDemo.java

    C:\Users\LuoYY\Desktop>java TestDemo
    keepRunning is false now
    loop terminates

Ответы [ 2 ]

1 голос
/ 10 марта 2019

Прочитайте еще раз:

"Компилятор может прочитать поле this.done только один раз"

свободен означает, что он может прочитать его только один раз,или он может читать его каждый раз, по своему усмотрению.В вашем случае он читает каждый раз, и это законное поведение, разрешенное спецификацией.

1 голос
/ 10 марта 2019

Спецификация не говорит, что компилятор (или среда выполнения) должен убедиться, что поле никогда не перезагружается и не синхронизируется с другими потоками.

"не должен", "свободен", "не имеет никакой семантики"

Это только говорит о том, что такое поведение разрешено (потому что оно имеет смысл в оптимизации производительности).

Поэтому, когда речь идет о нескольких потоках, вы должны четко указать, как он должен работать: либо сделать его энергозависимым, либо сделать его локальным для потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...