У потоков свои стеки, а процессор может держать данные в регистрах и кэшах. Если один поток пишет в обычное поле, а другой читает его без синхронизации, между этими действиями нет гарантированной связи в терминах Java Memory Model.
Нужна явная публикация состояния: запись в volatile, выход из synchronized, передача через потокобезопасную очередь, завершение потока с последующим join() или другой happens-before механизм. Сам по себе общий heap такой гарантии не даёт.
Подробнее: Процессы, потоки и память JVM.