学习笔记:volatile关键字总结

volatile关键字

  • 1、Java的内存模型

    Java内存模型简称JMM(Java Memory Model),是Java虚拟机所定义的一种抽象规范,用来屏蔽不同硬件和操作系统的内存访问差异,让java程序在各种平台下都能达到一致的内存访问效果。
    这里写图片描述
    注意:
    1、主内存是被所有线程共享的,主内存中存储了共享变量的“本体”;
    2、工作内存就是线程拥有的相互独立的内存空间,工作内存中有主内存中的变量,工作内存中存储的是共享变量的“分身”;

  • JMM的工作流程
    工作内存不能对主内存的对象进行直接的操作。
    首先经过内存读操作获取到“分身”;再对“分身”进行业务处理;最后把结果通过写操作将“分身”写回主内存的“ 本体“。这是一次完整过程。

  • JMM存在的问题
    因为存在着先读再处理最后写回的过程,就会出现 线程A读取后,处理中,写回前(可以假设成在写回主内存之前打了个断点)的时候,线程B从主内存进行读操作(读到此处停下来想一下这个场景)。这样线程A和线程B的变量内容会不一样。

  • *解决办法
    首先考虑上同步锁synchronized,但是会影响程序性能,除此之外,就是使用本文的主角:volatile关键字

  • volatile关键字的主要特性之一:保证可见性
    volatile最重要的特性之一就是保证了volatile修饰的变量对所有线程的可见性
    可见性的意思就是:
    当一个线程修改了变量的值,新的值会立刻同步到主内存当中。而其他线程读取这个变量的时候,也会从主内存中拉取最新的变量值。
    使用了volatile修饰的变量,会遵循先行发生原则,以上述例子来说,就是保证了线程B从主内存读取变量的动作,一定后发生于线程A写入主内存的动作
    注意:
    volatile只保证变量的可见性,并不能保证变量的原子性。这是因为volatile不能保证对变量的操作是原子性的,例如i++。

  • volatile关键字的主要特性之二:阻止指令重排
    指令重排的意思是:JVM在编译Java代码的时候,或者CPU在执行JVM字节码的时候,对现有的指令顺序进行重新排序
    指令重排的目的是为了在不改变单线程下程序执行结果的前提下,优化程序的运行效率
    但是在多线程的情况下,会影响程序的执行结果。使用volatile关键字则可以避免这种情况。如何做到的呢?是通过CPU指令:”内存屏障“解决的
    内存屏障包括了四种类型:
    LoadLoad屏障(读完再读)、StoreStore屏障(写完再写)、LoadStore屏障(读完再写)、StoreLoad屏障(写完再读)。
    在一个变量被volatile修饰后,JVM会为我们做两件事:
    1.在每个volatile写操作前插入StoreStore屏障,在写操作后插入StoreLoad屏障。
    2.在每个volatile读操作前插入LoadLoad屏障,在读操作后插入LoadStore屏障。

  • volatile关键字的其他特性:解决了long类型和double类型数据的8字节赋值问题

猜你喜欢

转载自blog.csdn.net/v_axis/article/details/78863801
今日推荐