volatile是怎么保证共享数据的可见性

  1. 简单聊聊 Java 虚拟机(Java Virtual Machine),总的来说 JVM 的架构师把 JVM 设置成了三大模块:类加载器(class loader sbusystem)、运行时数据区(runtime data areas)、执行引擎(execution engine)
    1. Java 源文件(即 .java 结尾的代码文件)通过 javac(编译器)把源代码编译成 JVM 可识别字节码文件(即 .class 结尾) 
    2. 类加载器读取字节码文件,并开始解析程序中定义的元数据(包括:变量、常量、类型、枚举等)把它们写入到方法区(运行时数据区之中)
    3. 运行时数据区连接(连接过程又分为:验证、准备、解析)类加载器写入到方法区的元数据
      1. 校验:字节码文件中元数据定义的准确性
      2. 准备:为这些元数据在内存中分配具体的内存空间
      3. 解析:为程序中定义的对象引用(逻辑)和内存地址编码(物理)建立起映射关系
    4. 经过运行时数据区之后程序中的元数据已经在内存中存在真实物理空间,接下来就是通过执行引擎来执行程序运算了,执行程序期间执行引擎可以调用本地方法库(native method libraries)
    5. 经过 JVM 之后程序就变成了一份真正意义上的机器码文件(二进制)计算机能直接执行的程序文件
    6. JVM 详情可以参考:https://blog.csdn.net/qq_41910568/article/details/90494434
  2. 主要说的 Java 内存模型(Java Memory Model),这个东西是 JVM 工程师用来指明 java 程序中的那些元数据在内存中存放位置以及在内存怎么操作这些元数据的一套规范。还有就是它屏蔽了各种硬件和操作系统的执行指令集,使 java 程序在跨平台特性上得到保证。
    1. 元数据在内存中的存放位置,可参考:https://blog.csdn.net/qq_41910568/article/details/90494434
    2. 屏蔽硬件和操作系统指令集,可参考其他资料。
    3. 操作内存中的元数据是这里的主角
      1. 进程是资源分配的基本单位
      2. 线程是 CPU 调度的基本单位
      3. 一个进程可以有多个线程,并且它们共享这个进程的资源
      4. 多核 CPU 情况下可以多个线程协同执行,这就需要线程间进行通信。
      5. 线程间通信可以通过进程的资源(相对于线程就是共享资源)
  3. 线程间通信(如下图所示)
    1. 线程01 <—— 主内存 ——> 线程02

   

  1. 内存可见性(volatile)
    1. 被 volatile 修饰的元数据在线程操纵它们的时候 JMM 有两个执行机制(load、store)可以保证元数据在内存中对所有线程的可见性
    2. load 机制:在每次有线程读取元数据的时候 JMM 都会执行load 操作把当前将要被操纵的元数据的最新值更新到内存中
    3. store 机制:线程每次操作完元数据之后 JMM 都会执行 store 操作把当前操纵的元数据更新到内存中
    4. 如下图所示:

    

  

 

好了本篇内容就到此了,欢迎大家的指教。。。。

原文地址:https://www.cnblogs.com/chaoyou/p/13555564.html