Как я и ожидал, поскольку логический тест не является изменчивым, Thread1 использует значение локального кэша теста, а когда Thread2 изменяет его на true, Thread1 ничего не будет делать.
Ваше ожидание неверно.
Согласно спецификации языка Java, если один поток обновляет энергонезависимую переменную общего доступа, а другой поток впоследствии читает ее без соответствующей синхронизации, тогда второй поток может увидеть новое значение или может увидеть более раннее значение.
Так что то, что вы видите, разрешено JLS.
На практике, когдаагент отладки присоединен к JVM, он обычно JIT компилирует методы на более низком уровне оптимизации ... или выполняет их, используя интерпретатор байт-кода.Это может произойти для методов с установленными в них точками останова, а также при одноступенчатом 1 .Это может привести к другому поведению для кода, который использует общие переменные без надлежащей синхронизации при его отладке.
Это одна из причин того, что проблемы с отладкой, вызванные неадекватной синхронизацией, являются трудными.
Насколько я знаю, точки останова меняют инструкции кода, добавляя специальную ловушку под названием INT 3. Так что же на самом деле происходит?
Вот что происходит при отладке C / C ++.Не указано, как JVM справляется с этим, но типичная JVM имеет другие варианты реализации точек останова ... из-за байт-кодов и компиляции JIT.
Когда я вставляю sleep(1)
воператор Thread1
before if также напечатает строку.Есть ли то же самое, что происходит при добавлении сна?
sleep
приведет к приостановке текущего потока.На уровне реализации не указано .Тем не менее, вероятно , что механизмы собственных потоков будут сбрасывать любые незавершенные записи (например, записи грязного кэша) для приостановленного потока в память ... как часть процесса выполнения переключения контекста потока.
Точно так же, если вы используете операторы print, типичный стек ввода-вывода имеет внутреннюю синхронизацию, которая может вызывать сброс кеша и т. Д. Это также может изменить поведение кода, который вы пытаетесь отлаживать.
Однако я должен подчеркнуть, что эти поведения не указаны.
1 - Оптимизатору JIT разрешено переупорядочивать назначения при условии, что это не изменяет однопоточное поведение.Но если вы отлаживаете метод и наблюдаете, что значения переменных, последствия переупорядочения видны (для программиста).Де-оптимизация / интерпретация избегает этого.К счастью, современный JVM / агент отладки может сделать это «на лету», как требуется.