java多线程数据可见性问题

下面这个程序缓存一致性问题,initflag第二个线程更改为true后,第一个线程while循环中如果没有输出那个代码或者加个同步块就跳不出循环。对于synchronized不应该是针对同一个监视器对象的话会保持内存可见吗? 再者initflag没有在同步代码块中包含,而是在while条件中,为什么线程1能够将自己的工作内存副本清除去主内存获取到线程2更改后的值呢?(不用volatile关键字)
package myTest;

public class ThreadMesiTest {
public static boolean initFlag = false;

public static void main(String[] args) throws InterruptedException {
    Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {             
            while(!initFlag){
                System.out.println("进来了");
            }
            System.out.println("获取到了新值跳出循环了");
        }
    });
    thread1.start();
    Thread.sleep(5000);
    Thread thread2 = new Thread(new Runnable() {
        @Override
        public void run() {
            initFlag = true;
            System.out.println("更新啦falg的值");
        }
    });
    thread2.start();
}

}

这个问题前几天回答过 可惜没被采纳
原因是因为
线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中
线程获取锁时,JMM会把该线程对应的本地内存置为无效,从主内存中读取共享变量
所以注意:
System.out.println("进来了"); 中
其实是有加synchronized锁的,所以子线程进入synchronized的时候会强制从主内存中读取共享变量,
当读取到true时,就跳出

线程 thread1 是先执行的,肯定能进入 while 循环打印“进来了” 。
5 秒后 thread2 修改了 initFlag 后,下一轮的 thread1 while 循环就结束了。

不知道你是怎么在 if 中添加同步块的,但是如果要加应该是这样的:

public void run() {
                while (true) {
                    synchronized (ThreadMesiTest.class) {
                        if(initFlag) {
                            break;
                        }
                    }
                    System.out.println("进来了");
                }
                System.out.println("获取到了新值跳出循环了");
            }

“为什么线程1能够将自己的工作内存副本清除去主内存获取到线程2更改后的值呢”应该不是这样的,线程1 读取变量时应该是从共享内存中获取的。

你是想问为什么没有锁或者volatile或者关键字,共享变量也能在主内存和工作内存中体现出及时的更新吧?

并不是说工作内存在没有同步处理的情况下就一定不会更新了,一般只有在短时间内高并发的情况才会出现不能及时刷新的情况,因为CPU在执行过程中会自行刷新缓存。

你可以多启动几个线程验证,或者在原来的程序上记录下时间戳。

当你的修改了initFlag了之后会有1毫秒(有时候甚至不到1毫秒的延迟)。