学习Java内存模型JMM心得

有时候编译器、处理器的优化会导致runtime与我们设想的不一样,为此Java对编译器和处理器做了一些限制,JAVA内存模型(JMM)将这些抽象出来,这样编写代码时就无需考虑那么多底层细节,并保证“只要遵循JMM的规则编写程序,其运行结果一定是正确的”。

JMM的抽象结构

在Java中,所有的实例、静态变量存储在堆内存中,堆内存是可以在线程间共享的,这部分也称为共享变量。而局部变量、方法定义参数、异常处理参数是在栈中的,栈内存不在线程间共享。

而由于编译器、处理器的优化,会导致共享变量出现可见性问题,像在多核处理器中(multi-processor),线程可以在不同的处理器上执行,而处理器之间缓存不一致,会使共享变量出现可见性问题,有可能两个线程看到同一个变量不同值。

JMM将这些硬件做的优化抽象成每个线程都有一个本地内存。需要读写共享变量时,从主内存中拷贝一份到本地内存。当写共享变量时,先写到本地内存中去,在将来某个时间再刷新到主内存中。当再次读共享变量时,则只会从本地内存中读取。

这样线程间通讯就需要经过两步:

写线程:刷新本地内存到主内存中去读线程:从主内存读取更新后的值

这样在写-读之间就有一个延迟:本地内存什么时候刷新到主内存中去?导致可见性问题,不同线程可能看到的共享变量不一样。

happens-before

从字面上看happens-before的意思是“发生在此之前”。这是java对程序执行顺序制定的规则,实现同步必须遵循该规则。这样程序员只需要写出正确的同步程序,happens-before保证运行结果不会错。

A happens-before B,不仅仅表示A在B之前执行,还意味着A的执行结果对B可见,这保证了可见性。

A happens-before B,A也不一定要在B之前执行,如果AB交替,执行结果任然正确,则允许编译器、处理器进行优化重排序。所以只要程序结果正确,编译器、处理器怎么优化,怎么重排序都没问题,都是好的。

happens-before规则

程序顺序规则:在一个线程中,前面的操作happens-before后面的操作锁规则:对同一个锁,解锁happens-before加锁 volatile域规则:写volatile变量,happens-before后面任意一个读这个volatile变量的操作传递性:A happens-before B,B happens-before C,则A happens-before C start()规则:如果线程A执行ThreadB.start() 那么ThreadB.start() happens-before 线程B中任何操作 join()规则:如果线程A执行ThreadB.join(),那么线程B中的所有操作happens-before ThreadB.join()

下面这个示例有助于理解happens-before

double pi = 3.14; //A
double r = 1.0; //B
double area = pi * r *r; //C

这里有三个happens-before关系,规则1、2是程序顺序规则,规则3是传递性规则推导出来的:

A happens-before B B happens-before C A happens-before C

C依赖于A、B,但是A和B谁也不依赖。所以即使A和B重排序,执行结果也不会发生变化,这种重排序,JMM是运行的。

下面两种执行顺序的结果都是正确的。

以上就是我们给大家整理的关于Java内存模型JMM学习心得的全部内容,更多问题大家可以在下方留言讨论,感谢你对我们的支持。

(0)

相关推荐

  • 学习Java内存模型JMM心得

    有时候编译器.处理器的优化会导致runtime与我们设想的不一样,为此Java对编译器和处理器做了一些限制,JAVA内存模型(JMM)将这些抽象出来,这样编写代码时就无需考虑那么多底层细节,并保证"只要遵循JMM的规则编写程序,其运行结果一定是正确的". JMM的抽象结构 在Java中,所有的实例.静态变量存储在堆内存中,堆内存是可以在线程间共享的,这部分也称为共享变量.而局部变量.方法定义参数.异常处理参数是在栈中的,栈内存不在线程间共享. 而由于编译器.处理器的优化,会导致共享变量

  • Java内存模型JMM详解

    Java Memory Model简称JMM, 是一系列的Java虚拟机平台对开发者提供的多线程环境下的内存可见性.是否可以重排序等问题的无关具体平台的统一的保证.(可能在术语上与Java运行时内存分布有歧义,后者指堆.方法区.线程栈等内存区域). 并发编程有多种风格,除了CSP(通信顺序进程).Actor等模型外,大家最熟悉的应该是基于线程和锁的共享内存模型了.在多线程编程中,需要注意三类并发问题: ·原子性 ·可见性 ·重排序 原子性涉及到,一个线程执行一个复合操作的时候,其他线程是否能够看

  • Java内存模型JMM与volatile

    目录 1.Java内存模型 2.并发三大特性 2.1.原子性 2.2.可见性 2.3.有序性 3.两个规则 3.1.happens-before规则 3.2.as-if-serial 4.volatile 4.1.volatile 禁止重排优化的实现 4.2.MESI缓存一致性协议 1.Java内存模型 JAVA定义了一套在多线程读写共享数据时时,对数据的可见性.有序性和原子性的规则和保障.屏蔽掉不同操作系统间的微小差异. Java内存模型(Java Memory Model)是一种抽象的概念,

  • JAVA内存模型(JMM)详解

    目录 前言 JAVA并发三大特性 可见性 有序性 原子性 Java内存模型真面目 Happens-Before规则 1.程序的顺序性规则 2. volatile 变量规则 3.传递性 锁的规则 5.线程 start() 规则 6.线程 join() 规则 使用JMM规则 方案一: 使用volatile 方案二:使用锁 小结: volatile 关键字 synchronized 关键字 总结 前言 开篇一个例子,我看看都有谁会?如果不会的,或者不知道原理的,还是老老实实看完这篇文章吧. @Slf4

  • Java内存模型(JMM)及happens-before原理

    我们知道java程序是运行在JVM中的,而JVM就是构建在内存上的虚拟机,那么内存模型JMM是做什么用的呢? 我们考虑一个简单的赋值问题: int a=100; JMM考虑的就是什么情况下读取变量a的线程可以看到值为100.看起来这是一个很简单的问题,赋值之后不就可以读到值了吗? 但是上面的只是我们源码的编写顺序,当把源码编译之后,在编译器中生成的指令的顺序跟源码的顺序并不是完全一致的.处理器可能采用乱序或者并行的方式来执行指令(在JVM中只要程序的最终执行结果和在严格串行环境中执行结果一致,这

  • 详细分析Java内存模型

    目录 一.为什么要学习并发编程 二.为什么需要并发编程 三.从物理机中得到启发 四.Java 内存模型 五.原子性 5.1.什么是原子性 5.2.如何保证原子性 六.可见性 6.1.什么是可见性 6.2.如何保证可见性 七.有序性 7.1.什么是有序性 7.2.如何保证有序性 一.为什么要学习并发编程 对于 "我们为什么要学习并发编程?" 这个问题,就好比 "我们为什么要学习政治?" 一样,我们(至少作为学生党是这样)平常很少接触到,然后背了一堆 "正确且

  • 并发编程之Java内存模型

    目录 一.Java内存模型的基础 1.1 并发编程模型的两个关键问题 1.2 Java内存模型的抽象结构 1.3 从源代码到指令重排序 1.4 写缓冲区和内存屏障 1.4.1 写缓冲区 1.4.2 内存屏障 1.5 happens-before 简介 简介: Java线程之间的通信对程序员完全透明,内存可见性问题很容易困扰Java程序员,这一系列几篇文章将揭开Java内存模型的神秘面纱. 这一系列的文章大致分4个部分,分别是: Java内存模型基础,主要介绍内存模型相关基本概念 Java内存模型

  • Java 内存模型(JMM)

    目录 四.Happens-Before 规则 Java 内存模型 一.什么是 Java 内存模型 Java 内存模型定义如下: 内存模型限制的是共享变量,也就是存储在堆内存中的变量,在 Java 语言中,所有的实例变量.静态变量和数组元素都存储在堆内存之中.而方法参数.异常处理参数这些局部变量存储在方法栈帧之中,因此不会在线程之间共享,不会受到内存模型影响,也不存在内存可见性问题. 通常,在线程之间的通讯方式有共享内存和消息传递两种,很明显,Java 采用的是第一种即共享的内存模型,在共享的内存

  • Java内存模型知识汇总

    为什么要有内存模型 在介绍Java内存模型之前,先来看一下到底什么是计算机内存模型,然后再来看Java内存模型在计算机内存模型的基础上做了哪些事情.要说计算机的内存模型,就要说一下一段古老的历史,看一下为什么要有内存模型. 内存模型,英文名Memory Model,他是一个很老的老古董了.他是与计算机硬件有关的一个概念.那么我先给你介绍下他和硬件到底有啥关系. CPU和缓存一致性 我们应该都知道,计算机在执行程序的时候,每条指令都是在CPU中执行的,而执行的时候,又免不了要和数据打交道.而计算机

  • Java内存模型相关知识总结

    [1]CPU和缓存的一致性 我们应该都知道,计算机在执行程序的时候,每条指令都是在CPU中执行的,而执行的时候,又免不了要和数据打交道.而计算机上面的数据,是存放在主存当中的,也就是计算机的物理内存啦. ​ 刚开始,还相安无事的,但是随着CPU技术的发展,CPU的执行速度越来越快.而由于内存的技术并没有太大的变化,所以从内存中读取和写入数据的过程和CPU的执行速度比起来差距就会越来越大,这就导致CPU每次操作内存都要耗费很多等待时间. ​ 所以,人们想出来了一个好的办法,就是在CPU和内存之间增

随机推荐