Количество ЦП не имеет значения, когда вы пытаетесь рассуждать о коде на этом уровне. Теоретически вы можете запустить JVM в ОС, которая вызывает переключение контекста после каждой отдельной инструкции программы. Это было бы безумием, и ни одна ОС этого не делает, но как вы узнаете, просто взглянув на код Java?
Если это исполнитель одного потока, то перекрытия не будет, а если это не один исполнитель потока, вы не сможете доказать, что перекрытия не будет.
Чтобы найти причину, нам нужно взглянуть на главу 17 JLS:
Два действия могут быть упорядочены отношением «происходит до». Если одно действие происходит раньше другого, то первое видно и упорядочено раньше второго.
Если у нас есть два действия x и y, мы пишем hb(x, y), чтобы указать, что x происходит раньше, чем y.
Если x и y являются действиями одного и того же потока и x предшествует y в программном порядке, то hb(x, y).
Существует край «происходит до» от конца конструктора объекта до начала финализатора (§12.6) для этого объекта.
Если действие x синхронизируется с последующим действием y, то мы также имеем hb(x, y).
Если hb(x, y) и hb(y, z), то hb(x, z).
Методы ожидания класса Object (§17.2.1) имеют связанные с ними действия блокировки и разблокировки; их отношения происходят до того, как они определяются этими связанными действиями.
Следует отметить, что наличие отношения «происходит до» между двумя действиями не обязательно означает, что они должны выполняться в этом порядке в реализации. Если изменение порядка приводит к результатам, согласующимся с законным исполнением, оно не является незаконным.
В случае исполнителя с одним потоком это именно то, что мы получаем: два исполняемых объекта являются действиями одного и того же потока, и один будет опережать другой в порядке выполнения программы. И хотя последний абзац позволяет переупорядочивать, переупорядочивание не может привести к видимым различиям в правильно синхронизированном коде.
С несколькими потоками можно только догадываться. Есть только две вещи, которые гарантированы:
- Первое сообщение из потока будет напечатано перед вторым. (см. выше)
- И каждая строка вывода будет содержать полное сообщение из одного из потоков, т.е. вы никогда не увидите строку перемешанного вывода. Это просто потому, что
PrintStream.println()
синхронизировано.
Итак, это теория.
На практике с большинством реализаций JVM и операционных систем вы, вероятно, никогда не увидите совпадений с этим точным кодом по той простой причине, что выполняемые вами задачи требуют слишком мало времени для прерывания. Заставьте их работать в течение нескольких минут или часов, и вы обязательно увидите переключение контекста между ними.
person
biziclop
schedule
01.03.2017