Java内存模型
Posted chenchenxiaobao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java内存模型相关的知识,希望对你有一定的参考价值。
内存模型
线程间通信
Java线程间的通信方式一般有共享内存及消息两种方式,其中消息通信一般为传统的wait()和notify()方法来实现线程间的显式通信。而另外一种则是采用共享内存来实现隐式通信。
内存模型概述
在Java内存模型(JMM)中,大致如下图所示:
??
(1)、线程A将本地变更的副本刷新到主存中去;
(2)、线程B从主存中读取共享变量。
具体步骤如下图所示:
??
指令重排序
1、编译器优化重排序(前提:不改变单线程程序语义);
2、现代处理器支持的指令级并行重排序(前提:不存在数据依赖性);
3、由于CPU通过缓存来实现读写,还会进行内存系统重排序。
如下图所示:
??
其中1是属于编译器重排序,2和3是属于处理器重排序,在处理器重排序之前。JMM会要求编译器在生成
指令序列时要插入特定类型的内存屏障(Memory Barriers),通过内存屏障指令来禁止某些特定类型的处理器重排序。
重排序对多线程编程的影响
public class ReorderingTest {
int a = 0;
boolean flag = false;
int result = 0;
private void write() {
a = 1;
flag = true;
}
private void read() {
if (flag) {
result = a * a;
System.out.println("result=" + result);
}
}
}
如果有两上线程A和B,线程A调用完write()方法之后,线程B去调用read()方法,result打印出来未必是1,也有可能是0。因为重排序可能导致线程A先执行flag=true,再执行a=1;因为在单线程环境下把a=0与flag=true并无依赖关系。
happens-before
在JMM中,如果一个操作的结果对于另一个操作是可见的,那么我们就说这两个操作之间存在着happens-before关系。
happens-before规则如下:
1、程序顺序规则:一个线程中的每一个操作都happens-before于后续的所有操作;
2、监视器锁规则:对一个锁的解锁,happens-before于对这个锁的加锁;
3、volatile变量规则:对一个volatile变量的写,都happens-before于任意后续对该变量的读;
4、传递性:如果A happens-before B,B happens-before C,那么A happens-before C。
注意:两个操作之间具有happens-before关系,不一定前一个操作必须要在后一个操作之前得到执行!happens-before规则仅仅只是要求前一个操作的结果对于后一个操作是可见的。
以上是关于Java内存模型的主要内容,如果未能解决你的问题,请参考以下文章
深入理解Java内存模型
Java内存模型
Java内存模型
java内存模型的JMM简介
并发艺术--java内存模型
Java内存模型的历史变迁