为什么线程之间会存在可见性原因?
JVM运行程序的实体是线程,每个线程在被创建时JVM都会为其创建一个自己私有的工作内存。而Java内存模型规定所有的变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但是线程对这些变量的操作只能在自己的工作内存中进行,不能直接操作主内存中的变量,要先将变量从主内存中拷贝到线程自己的工作内存中再对其进行操作,操作完成后再将操作后的变量写回主内存当中,因此不同的线程也无法访问对方的工作内存,线程间的通信必须通过主内存来完成。
怎样保证可见性
volatile是java提供的轻量级同步机制,能保证线程可见性,但是不能保证原子性(原理省略)
但是在以下代码中,会出现没有使用volatile情况下,不同线程仍然保证了可见性:
public class Test {
static Boolean flag = true;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while (flag){
}
System.out.println("jieshu ");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
flag = false;
System.out.println("xxxxxxxx");
}
}).start();
}
}
原因是什么呢?
首先我们得知道JVM 有两种启动模式分别为 Server模式与client模式,server模式启动慢但是运行效率比client高很多倍。
在虚拟机的client模式下,由于JIT并没有做出足够的优化,在Thread2修改flag变量的状态后,Thread1可发现这个改动,并退出程序。但是在server模式下,由于系统优化的结果,Thread1线程无法看到这个改动