『每日一问』简单聊聊JMM/说说对JMM的了解

『每日系列』

                      ☟☟☟

           ☟☟☟)

JMM是什么

Java Memory Model , Java内存模型,简称JMM。
Java线程之间的通信由JMM控制。JMM决定了一个线程对共享资源的写何时对另一个线程可见。从抽象的角度讲,JMM定义了线程和主内存之间的关系,每个线程都有一个本地内存1,存储了主内存中共享资源的「副本」。

JMM内存模型

JMM内存模型
上边说过了,JMM控制线程通信。那么如图线程A、B是如何通信的呢

  1. 线程A将自己本地内存中的共享变量刷新到主内存
  2. 线程B将自己本地内存中的副本置为无效,读取主内存中的共享变量值

以上两步可以看出来

  • 线程之间的通信必须经过主内存。
  • JMM通过控制每个线程的本地内存和主内存的交互,向我们提供内存可见性保证。
重排序

在一个程序执行的时候,为了优化程序性能,编译器和处理器常常会对指令做重排序。重排序可能会导致多线程程序出现内存可见性问题。

JMM对这两种类型重排的处理和要求:

  • 对于编译器重排序:JMM会禁止特定类型的编译器重排序。 那么是哪些呢?
  • 对于处理器重排序:JMM会要求Java编译器在生成指令序列的时候,插入特定类型的内存屏障(Memory Barries)来禁止特定类型的处理器重排序。

JMM作为一个语言级的内存模型,在不同的编译器和处理器上,通过禁止特定类型的编译器和处理器重排序,提供一致的内存可见性保证。

数据依赖性

如果两个操作访问同一个变量,且这两个操作中有一个是写操作,那么这两个操作之间就存在数据依赖性。
产生数据依赖性的操作有三种:

  1. 读后写
  2. 写后读
  3. 写后写
    以上三种操作,如果顺序被重排,那么程序的结果就会被改变。
as-if-serial语义

as-if-serial(串行化)的语义是:不管编译器和处理器为了提供并行度做怎样的重排序,单线程程序的执行结果不能被改变2
那么为了达到这个效果,编译器和处理器不会对存在数据依赖性的操作做重排序。

A
C
B

如图,C分别与A、B都有数据依赖关系,那么C就不会被重排在A、B任何一个之前去执行。
那么最后可能的顺序就是:

A
B
C
B
A
C
happens-before

如果一个操作happens-before另一个操作,那么第一个操作的执行结果对第二个操作可见,但是第一个操作的执行顺序不一定排在第二个之前。如果这两个操作由数据依赖关系,那么第一个操作就排在第二个之前,反之亦然。
多线程之间操作的happens-before关系的确立是依靠着代码上的正确同步


  1. 本地内存是JMM的一个抽象概念,并不真实存在,其实是涵盖了缓存、写缓冲区、寄存器以及其他硬件和编译器的优化。 ↩︎

  2. as-if-serial把单线程程序保护了起来,同时也会制造一个幻觉:单线程代码的执行顺序和写的代码顺序是一致的。 ↩︎

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值