Java内存模型(JMM)

JMM(Java内存模型)

概念

Java 内存模型(Java Memory Model,JMM)定义了 Java 程序中的变量、线程如何和主存以及工作内存进行交互的规则。它主要涉及到多线程环境下的共享变量可见性、指令重排等问题,是理解并发编程中的关键概念。JMM的目的是为了解决多线程环境下的内存(本地内存)一致性问题。

在多线程的情况下,会出现多个线程对同一共享变量同时读取,但是这会产生脏读,不可重复读,幻读等问题。JMM 中定义的规则,控制了本地内存和主存中的交互,来保证内存可见性,这样也就知道这个变量正在被更改,保证变量的可见性。

例如:volatile 和 synchronized。

注意 JMM 和 JVM 运行时数据区 不是一个东西 ,JMM 是抽象的,他是一组规则。

指令重排序

系统执行代码的顺序不一定是你写的代码的顺序。

为什么要指令重排序?

计算机在执行过程中,为了提高性能,会对编译器和编译器做指令重排序。

为了提高利用率以及程序的性能, Java 虚拟机会在你这个指令还没完全执行完毕的时候,就去执行另外一个指令。这就是流水线技术

我们知道计算机在执行的时候都是一个个指令去执行,不同的指令可能操作的硬件不一样,在执行的过程中可能会产生中断,打个比方,两个指令a和b他们操作的东西各不相同,如果加载a的时候停顿了,b就加载不到,但是实际上它们互补影响,我也可以先加载b在加载a,所以指令重排是减少停顿的一种方法,这样大大提高了效率。

导致问题

指令重排序会导致乱序的问题。

指令重排序分三种:

  • 编译器优化重排,编译器在不改变单线程程序语义的前提下,重新安排语句的执行顺序。

  • 指令并行重排,现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性(即后一个执行的语句无需依赖前面执行的语句的结果),处理器可以改变语句对应的机器指令的执行顺序。

  • 内存系统重排,由于处理器使用缓存和读写缓存冲区,这使得加载(load)和存储(store)操作看上去可能是在乱序执行,因为三级缓存的存在,导致内存与缓存的数据同步存在时间差。

由上面的三种重排序可以看出来,指令重排序可以保证串行语义一致(单线程情况下不会导致结果错误),但是多线程情况下,会导致结果出现问题。

JMM和顺序一致性

顺序一致性模型是一个理想化的内存模型,它假设所有线程的操作都是按照某种全局一致的顺序执行的,每个线程的操作都按照程序指定的顺序对所有线程可见。在顺序一致性模型中,不存在重排序、缓存和优化等问题,所有线程看到的内存状态都是一致的。

关键词 -- 执行顺序和写入顺序相同,共享变量对所有线程可见

JMM 和 顺序一致性模型的区别
重排序

JMM 是有重排序的,为了提高效率。顺序一致性模型完全按照写入顺序执行,没有重排序。

可见性

在JMM中,线程对共享变量的修改并不总是立即对其他线程可见。并且利用了某些方式去改变共享变量的可见性,例如:volatile,synchronized 等。

顺序一致性模型保证所有线程看到的内存状态都是一致的。


happens-before原则

ok 说了这么多 ,JMM 怎么保证在多线程情况下,结果不出错?靠的都是happen - before 原则。

对于编译器而言,只要不改变程序最终运行出的结果,无论怎么换顺序都行,这样 JMM 找到了平衡点。

内容
  1. 如果一个操作 happens-before 另一个操作,那么第一个操作的执行结果将对第二个操作可见,并且第一个操作的执行顺序排在第二个操作之前。

  1. 两个操作之间存在 happens-before 关系,并不意味着 Java 平台的具体实现必须要按照 happens-before 关系指定的顺序来执行。如果重排序之后的执行结果,与按 happens-before 关系来执行的结果一致,那么 JMM 也允许这样的重排序。

传递规则:如果 A happens-before B,且 B happens-before C,那么 A happens-before C;

总结

如果 A happens-before B,那么无论这两个操作在不在一个线程内,都要保证 A 对 B 可见。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值