I am learning about volatile of Java and my code is like this.
public class Test {
    public static boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            while(flag){
                // System.out.println(flag);
            }
            System.out.println("end");
        });
        t1.start();
        Thread.sleep(100);
        Thread t2 = new Thread(()->{
            flag = false;
            System.out.println("changed");
        });
        t2.start();
    }
}
I know if flag doesn't have volatile, the thread would not exist. It's a visibility problem.
However if I write some code in the while loop, like System.out.println("abc"), t1 thread will read the new value and stop the loop.
I know how to use volatile to resolve the visibility problem, so my question is:
Why t1 can read the new value of flag when I write System.out.println("abc") in the while loop?
 
     
    