JMM(java memory model)java内存模型主要目标是定义程序中的变量,(此处所指的变量是实例字段、静态字段等,不包含局部变量和函数参数,因为这两种是线程私有无法共享)在虚拟机中存储到内存与从内存读取出来的规则细节,Java 内存模型规定所有变量都存储在主内存中,每条线程还有自己的工作内存,工作内存保存了该线程使用到的变量到主内存副本拷贝,线程对变量的所有操作(读取、赋值)都必须在自己的工作内存中进行而不能直接读写主内存的变量,不同线程之间无法相互直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成。

Java 内存模型对主内存与工作内存之间的具体交互协议定义了八种操作,具体如下:

  • lock(锁定):作用于主内存变量,把一个变量标识为一条线程独占状态。

  • unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。

  • read(读取):作用于主内存变量,把一个变量从主内存传输到线程的工作内存中,以便随后的 load 动作使用。

  • load(载入):作用于工作内存变量,把 read 操作从主内存中得到的变量值放入工作内存的变量副本中。

  • use(使用):作用于工作内存变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量值的字节码指令时执行此操作。

  • assign(赋值):作用于工作内存变量,把一个从执行引擎接收的值赋值给工作内存的变量,每当虚拟机遇到一个需要给变量进行赋值的字节码指令时执行此操作。

  • store(存储):作用于工作内存变量,把工作内存中一个变量的值传递到主内存中,以便后续 write 操作。

  • write(写入):作用于主内存变量,把 store 操作从工作内存中得到的值放入主内存变量中。

如果要把一个变量从主内存复制到工作内存就必须按顺序执行 read 和 load 操作,从工作内存同步回主内存就必须顺序执行 store 和 write 操作,但是 JVM 只要求了操作的顺序而没有要求上述操作必须保证连续性,所以实质执行中 read 和 load 间及 store 和 write 间是可以插入其他指令的。

Java 内存模型还会对指令进行重排序操作,在执行程序时为了提高性能编译器和处理器经常会对指令进行重排序操作,重排序主要分下面几类:

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

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

  • 内存系统重排序:由于处理器使用缓存和读写缓冲区使得加载和存储操作看上去可能是在乱序执行。

其实 Java JMM 内存模型是围绕并发编程中原子性、可见性、有序性三个特征来建立的,关于原子性、可见性、有序性的理解如下:

  • 原子性:就是说一个操作不能被打断,要么执行完要么不执行,类似事务操作,Java 基本类型数据的访问大都是原子操作,long 和 double 类型是 64 位,在 32 位 JVM 中会将 64 位数据的读写操作分成两次 32 位来处理,所以 long 和 double 在 32 位 JVM 中是非原子操作,也就是说在并发访问时是线程非安全的,要想保证原子性就得对访问该数据的地方进行同步操作,譬如 synchronized 等。

  • 可见性:就是说当一个线程对共享变量做了修改后其他线程可以立即感知到该共享变量的改变,从 Java 内存模型我们就能看出来多线程访问共享变量都要经过线程工作内存到主存的复制和主存到线程工作内存的复制操作,所以普通共享变量就无法保证可见性了;Java 提供了 volatile 修饰符来保证变量的可见性,每次使用 volatile 变量都会主动从主存中刷新,除此之外 synchronized、Lock、final 都可以保证变量的可见性。

  • 有序性:就是说 Java 内存模型中的指令重排不会影响单线程的执行顺序,但是会影响多线程并发执行的正确性,所以在并发中我们必须要想办法保证并发代码的有序性;在 Java 里可以通过 volatile 关键字保证一定的有序性,还可以通过 synchronized、Lock 来保证有序性,因为 synchronized、Lock 保证了每一时刻只有一个线程执行同步代码相当于单线程执行,所以自然不会有有序性的问题;除此之外 Java 内存模型通过 happens-before 原则如果能推导出来两个操作的执行顺序就能先天保证有序性,否则无法保证,关于 happens-before 原则可以查阅相关资料。

所以说如果想让 Java 并发程序正确的执行必须保证原子性、有序性、可见性,只要三者中有任意一个不满足并发都无法正确执行。

深入理解内存模型JMM的更多相关文章

  1. 全面理解Java内存模型(JMM)及volatile关键字(转载)

    关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoad ...

  2. 全面理解Java内存模型(JMM)及volatile关键字(转)

    原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型( ...

  3. 深入理解Java内存模型JMM与volatile关键字

    深入理解Java内存模型JMM与volatile关键字 多核并发缓存架构 Java内存模型 Java线程内存模型跟CPU缓存模型类似,是基于CPU缓存模型来建立的,Java线程内存模型是标准化的,屏蔽 ...

  4. 深入理解Java内存模型JMM

    本文转载自深入理解Java内存模型JMM JMM基础与happens-before 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执 ...

  5. Java内存模型JMM与可见性

    Java内存模型JMM与可见性 标签(空格分隔): java 1 何为JMM JMM:通俗地讲,就是描述Java中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取变量这 ...

  6. 多线程并发之java内存模型JMM

    多线程概念的引入是人类又一次有效压寨计算机的体现,而且这也是非常有必要的,因为一般运算过程中涉及到数据的读取,例如从磁盘.其他系统.数据库等,CPU的运算速度与数据读取速度有一个严重的不平衡,期间如果 ...

  7. Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)

    JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...

  8. 高并发第二弹:并发概念及内存模型(JMM)

    高并发第二弹:并发概念及内存模型(JMM) 感谢 : 深入Java内存模型 http://www.importnew.com/10589.html, cpu缓存一致性 https://www.cnbl ...

  9. 什么是Java内存模型(JMM)

    什么是java内存模型 缓存一致性问题 在现代计算机中,因为CPU的运算速度远大于内存的读写速度,因此为了不让CPU在计算的时候因为实时读取内存数据而影响运算速度,CPU会加入一层缓存,在运算之前缓存 ...

随机推荐

  1. 2018.02.12 noip模拟赛T2

    二兵的赌注 Description游戏中,二兵要进入了一家奇怪的赌场.赌场中有n个庄家,每个庄家都可以猜大猜小,猜一次一元钱.每一次开彩前,你都可以到任意个庄家那里下赌注.如果开彩结果是大,你就可以得 ...

  2. Linux批量修改(删除)文件名某些字符(rename命令)

    假设在路径C:/下存在多个类似以下的文件名 file_nall_abc1.txt file_nall_abc2.txt file_nall_abc3.txt file_nall_abc4.txt fi ...

  3. Druid 配置及内置监控,Web页面查看监控内容 【我改】

    转: Druid 配置及内置监控,Web页面查看监控内容 1.配置Druid的内置监控 首先在Maven项目的pom.xml中引入包 1 2 3 4 5 <dependency>      ...

  4. Redis:默认配置文件redis.conf详解

    转: Redis:默认配置文件redis.conf详解 # Redis配置文件样例 # Note on units: when memory size is needed, it is possibl ...

  5. Installation failed with message Failed to finalize session: INSTALL_FAILED_TEST_ONLY:installPackageLI.

    这样还不行的话,加 -t吧.

  6. springboot1.5升级2.0后遇到的问题

    https://blog.csdn.net/zhiquanzhou/article/details/80566630

  7. 114. Flatten Binary Tree to Linked List(M)

    . Flatten Binary Tree to Linked List Given a binary tree, flatten it to a linked list in-place. For ...

  8. 打印流(PrintWriter )

    PrintWriter package cn.lijun.demo1; import java.io.File; import java.io.FileNotFoundException; impor ...

  9. 一键开启MacOS HiDPI

    完整文件下载:一键开启MacOS HiDPI 引言 作为一个黑苹果用户,追求黑果的体验是当然的,当各个硬件都驱动完善后,要做的就是细节的优化了,毕竟装上是拿来用的,可不能因为体验差苦了自己啊.机器毕竟 ...

  10. Linux基础-兄弟连Linux

    Linux基础增强与辅助知识梳理... ------------ Linux学习基础需要学习那些知识 学习Linux对于程序开发的好处 怎样开始学习Linux Linux的学习方法参考 Linux系统 ...