这篇文章我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况。来聊聊java线程对一个变量的更新怎么通知另一个线程,及volatile的作用和指令重排序的问题。

内存模型

  首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做呢,又或者说,一个java线程对一个变量的更新怎么通知到另外一个线程呢?我们知道java当中的实例对象、数组元素都放在java堆中,java堆是共享的(这里我们把java堆称为主内存)。而每一个线程都是自己私有的内存空间(称为工作内存),如果线程1要向线程2通信,一定会经过以下类似的流程:

    

  1、线程1将自己工作内存中的X更新为1并刷新到主内存中;

  2、线程2从主内存中读取变量X=1,更新到自己的工作内存中,从而线程2读取的X就是线程1更新后的值。

从上面的流程看出线程之间的通信都需要经过主内存,而主内存与工作内存的交互,则需要java内存模型(JMM)来管理。下图演示了JMM如何管理主内存和工作内存:

当线程1需要将一个更新后的变量值刷新到主内存中时,需要经过两个步骤:

  1、工作内存执行store操作(存储操作);

  2、主内存执行write操作(写操作);

完成这两个操作即可将工作内存中的变量值刷新到主内存中,即线程1工作内存和主内存的变量值保持一致;

当线程2需要从主内存中读取变量的最新值时,同样需要经过两个步骤:

  1、主内存执行read操作,将变量值从主内存中读取出来;

  2、工作内存执行load操作,将读取出来的变量值更新到本地内存的副本;

完成这两步,线程2的变量和主内存的变量值就保持一致了。

可见性

  java中有一个关键字 volatile,它有什么用呢?(没有volatile会出现的情况举例!

  这个答案其实就在上面说java线程间通信机制中,我们想象一下,由于工作内存这个中间层的出现,线程1和线程2比如存在延迟的问题,例如线程1在工作内存中更新了变了,但是还没有刷新到主内存,而此时线程2获取到的变量值就是还未更新的变量值,又或者线程1成功将变量更新到主内存,但是线程2依然使用主键工作内存中的变量值,同样会出现问题。不管出现哪种情况都可能导致线程间的同学不能达到预期的目的。

//线程1
boolean stop = false; while(!stop){ doSomething(); }
//线程2
stop = true;

  这个例子表示线程2通过修改stop的值,来控制线程1的中断,但是在真是环境中可能会出现意想不到的结果,线程2在执行之后,线程1并没有立刻中断甚至一直不会中断。出现这种情况的原因就是线程2对线程1的变量更新无法第一时间获取到。

但是这一些等到volatile出现后,就不会出现了。volatile保证两件事情:

  1、线程1工作内存中的变量更新会强制立即写入到主内存;

  2、线程2工作内存中的变量会强制立即失效,这使得线程2必须去住线程中获取最新的变量值。

所以这就理解了volatile保证了变量的可见性。因为线程1对变量的修改能第一时间让线程2可见。

转载于:https://www.cnblogs.com/MoreThinking/p/9884561.html

JVM知识(三):内存模型和可见性相关推荐

  1. JVM学习--(二)内存模型、可见性、指令重排序

    我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存模型 首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做,我们再 ...

  2. JAVA学习笔记--4.多线程编程 part1.背景知识和内存模型

    2019独角兽企业重金招聘Python工程师标准>>> 背景知识 CPU Cache 如上简易图所示,在当前主流的CPU中,每个CPU有多个核组成的.每个核拥有自己的寄存器,L1,L ...

  3. jvm(12)-java内存模型与线程

    [0]README 0.1)本文部分文字描述转自"深入理解jvm",旨在学习"java内存模型与线程" 的基础知识: [1]概述 1)并发处理的广泛应用是使得 ...

  4. Java虚拟机(JVM)与Java内存模型(JMM)学习笔记

    Java虚拟机[JVM]与Java内存模型[JMM]学习笔记 Java虚拟机(JVM) 三种JVM JVM 位置 JVM的主要组成部分及其作用 类加载器 双亲委派机制 沙箱安全机制 Java本地接口( ...

  5. JVM之Java内存模型(基于《深入理解Java虚拟机》之第12章Java内存模型与线程)(上)

    多任务处理为什么在OS中几乎是一项必备的功能? sadsa sadsa①.计算机的运算能力强大了,但其运算速度与它的存储和 通信子系统的速度 差距太大了,不匹配,大量的时间都花费在磁盘I/O.网络通信 ...

  6. Java工程师必备:JVM原理、内存模型、调优、垃圾回收机制、面试题

    在如今这个时间和知识都是碎片化的时代,C站根据C1-C4认证的成长路径,进行知识细化整理,形成系统化的知识图谱. 通过调研一线互联网大厂的招聘JD,小编对标C站能力认证要求,为大家整理了系列技术干货合 ...

  7. JVM学习 - 体系结构 内存模型

    2019独角兽企业重金招聘Python工程师标准>>> 一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代" ."非堆&quo ...

  8. JVM学习-Java内存模型JMM

    目录 1.Java内存模型概述 2.原子性 2.1.问题提出 2.2.问题分析 2.3.解决办法 3.原子性 3.1.退不出的循环 3.2 解决方法 3.3 可见性 4.有序性 4.1.诡异的结果 4 ...

  9. [JVM]了断局:内存模型与线程

    一.前言 Java内存模型的主要目的是定义程序中各种变量的访问规则, 即关注在虚拟机中把变量值存储到内存和从内存中取出变量值这样的底层细节. Java内存模型规定了所有的变量都存储在主内存(Main ...

最新文章

  1. 【怎样写代码】对象克隆 -- 原型模式(二):解决方案
  2. 建房子 最安全图纸_农村建什么样的房子合适?分享15套图纸,总有一套适合你...
  3. 以技术面试官的经验分享毕业生和初级程序员通过面试的技巧(Java后端方向)...
  4. hdu4067 费用流(混合欧拉的宽展和延伸)
  5. javaaop模式供其他项目调用_Java 分布式架构的 开源的支付项目 调试实战
  6. proto的介绍和基础使用
  7. linux下编译安装ACE-6.5.1
  8. 1.4 如何学习设计模式
  9. sublimeText3安装、激活、环境配置与代码补全神器Kite安装配置
  10. scl语言用plc脉冲做定时器_请问SCL语言如何调用定时器
  11. 李智慧-我的全栈之路导师之一
  12. ch341a编程和ttl刷机区别_USB转TTL(CH341A)的注意事项及说明 -
  13. 模拟山羊收获日Android,模拟山羊收获日手机版
  14. 怎么理解——用户不是人
  15. Android 连接USB设备(主机模式)
  16. 树莓派挂载和卸载U盘或移动硬盘
  17. GParted图形化工具对Linux磁盘分区扩容
  18. 【JAVA 求差集】
  19. 媒体格式有几种,媒体格式的异同
  20. 实验5-三种基本结构综合应用:7-3 龟兔赛跑 (20 分)

热门文章

  1. 刷新所有视图存储过程
  2. iview表格嵌套Tooltip
  3. nginx 配置后网站图片加载出来一半或者不出来
  4. 经历越多困难,你就变的更韧性
  5. UIDatePicker的使用
  6. python学习之路-书籍推荐
  7. 使用RQShineLabel
  8. 卡巴斯基亚太区总经理:不做免费杀毒厂商
  9. 程序员很忙吗_当一个程序员一天被打扰 10 次,后果很惊人!
  10. linux vi 上下左右 ab,【Linux】Ubuntu vi 上下左右变ABCD及 apt-get install报错问题解决方法...