Вы делаете много предположений о темах, которые не соответствуют действительности.
Вот два основных ваших предположения, которые не соответствуют действительности:
- Все потоки работают с одинаковой скоростью.
- Все темы запускаются сразу.
Последовательность выполнения является случайной.
Потоки работают одновременно.
Далее последовательность означает последовательность, в которой потоки нажимают SynchronizedCounter
через вызовы метода. Поскольку это то, что делает synchronized
, он принудительно запускает параллельные потоки в последовательный доступ, защищая его с помощью монитора (если вы не знаете, что такое монитор, вместо этого читайте семафор мьютекса, это другое, но для этого объяснения разница не важный).
Можно ожидать любой из следующих трех выходов:
0
в случае, если последовательность была D, E, main; или E, D, главный; или основной, D, E; или основной, E, D.
1
в случае последовательности D, main, E
-1
в случае последовательности E, main, D.
Темы не запускаются сразу
Когда вы вызываете new Thread().start()
, Thread
становится работоспособным. Но планировщик должен решить, когда поток действительно получает процессорное время. И это зависит от факторов вне сферы влияния программы, иногда даже вне сферы влияния виртуальной машины. Например, насколько близок какой-либо из существующих потоков к вытеснению из-за исчерпания его временного интервала, или из-за того, доступны ли незанятые ядра ЦП прямо сейчас.
Потоки бегут на разных скоростях
Скорость потока определяется различными факторами, которые находятся за пределами влияния программы. Например, если поток хочет получить доступ к данным, независимо от того, кэшируются ли эти данные и в каком кеше он находится, привести только один пример.
Выход -1
является наиболее маловероятным выходом, но даже этот выход нельзя полностью исключить. И это «маловероятное» также основано исключительно на предположениях, сделанных из наблюдений о том, как обычно ведут себя виртуальные машины, и на это нельзя полагаться.