理解JAVA内存模型(JMM)

JMM是一个抽象的概念,他并不是真实存在的东西。只是java为了消除各个平台和系统上堆内存访问差异而定义的一个模型。他主要控制了线程与线程之间的通信,线程与内存之间的交互。它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。如图所示:
在这里插入图片描述
下面介绍JMM几个比较重要的概念:
1.对执行的重排序,JMM会在保证执行结果正确(单线程下)的前提下对指令进行重排序。但也正是因为重排序的从在,所以在多线程的情况下会发生许多在单线程情况下不会出现的问题。重排序会经历一下几个过程:
在这里插入图片描述
2.happens-before的概念:
字面意思叫发生于之前。他有以下几种规则:
·程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
·监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
·volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的 读。
·传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。
按照字面意思,A happens-before B 不代表A一定要在B之前执行,只需要保证A操作的结果在B执行前是对B可见的。
3. as-if-serial语义
不管怎么重排序(编译器和处理器为了提高并行度),(单线程) 程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义。
如下代码所示:

double a = 3.14; //语句a
double b = 1.0; //语句b
double area = a * b * b; //语句c

JMM可能会对这段代码的执行顺序进行重排序,但是无论怎么排序 a 与 b 的执行都必须happens-before c。因为c的结果依赖与a 与 b的值。因为c结果依赖a与b的值。
所以我们无需担心重排序对单线程的结果有什么影响,但是在多线程之下,重排序往往会造成意想不到的记过。

int a = 0;
boolean flag = false;
//线程A执行
public void writer(){
a = 1;
flag = true;
}

//线程B执行
public void reader(){
if(flag) {
//如果传入a=0会有错误。
doSomeThings(a);
}
}

如上段代码,A,B两个线程分别执行读/写方法。按照正常的逻辑应该是给a赋值1之后再对flag进行赋值。如果进行了重排序,A执行的线程就会先把flag = true执行如果此时B线程去执行读方法,就会把a = 0传入doSomeThings()方法中。就会造成报错。当然此处有很多解决办法,加入volatile关键字等都可以防止重排序。不理的可以看这里volatile关键字解析
小结:JMM,内存模型也就是各种内存可见性的问题。相信理解了JMM。也会对并发编程的水平有着一定的提升。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值