由指令重排序引起的可见性问题:
public class Test {
// 如果运行时加上 -server 下面的代码就变成了死循环,没有加就正常运行。(运行器的编译优化只有在服务器模式下才执行)
// 通过设置JVM参数,打印出JIT(即时编译)编译的内容(这里说的编译不是指class文件的编译,而是指未变级别的编译)
private boolean flag = true;
// -server -Djava.compiler=NONE 参数可以关闭jit优化。
// 在多线程中,由于指令重排序引起的线程可见性问题。
public static void main(String[] args) throws IOException, InterruptedException {
Test demo1 = new Test();
new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
// class文件在运行时jit编译成为汇编指令,汇编指令出现了重排序。
/*
// 重排序后的逻辑。因为while语句里面需要一直判断flag。所以jvm优化为外层使用if判断一次。
if(demo1.flag){
while (true){
i++;
}
} hot code : 热点代码。(就像是下面的while语句中的内容,执行频率很高。jvm认为是热点代码)
*/
while (demo1.flag) {
i++;
}
System.out.println("i = " + i);
}
}).start();
TimeUnit.SECONDS.sleep(2);
// 设置flag为false,使上面的线程结束循环。
demo1.flag = false;
System.out.println("主线程结束");
}
}
问题描述:
多个CPU执行多个线程任务时,由于线程栈时独享的,如果共享数据在缓存中跟新不及时,会出现多线程共享数据不一致。(基本不可能出现)
运行时编译器JIT,将class编译称为汇编指令。在服务器模式下。会对执行的顺序进行优化重排序。但是放在多线程中执行时会由于执行的顺序改变执行的结果。
由于指令进行了重排序。导致缓存的修改对本线程不可见。
(指令重排序导致了while语句变成了if执行,之后在多线程的情况下。一个线程先判断if,另外一个线程后修改条件。所以if语句中的内容不会执行了。)
(指令重排序是为了:提高CPU的使用率。一个线程阻塞的时候,别的线程继续执行。)
内存模型规范(为了使共享数据及时可见):
可以在线程之间共享的内存称为:共享内存或堆内存。所有实例字段、静态字段和数组元素都存储在堆内存中。
定义了线程的操作:write、read、lock、unlock、启动、终止、同步规则(加锁解锁)
如果一个线程没有数据竞争,那么程序的所有执行看起来都是顺序一致的。
oracle文档官网:
docs.oracle.com
来源:https://www.cnblogs.com/Xmingzi/p/12601067.html