java中volatile关键字的作用

文章目录

  • 前言
  • 1、volatile
    • 1.1、volatile保证可见性
    • 1.2、volatile保证顺序性
      • 1.2.1、重排序与内存屏障
      • 1.2.2、jvm中的内存屏障
      • 面试题:DCL单例加不加volatile


前言

记录java线程相关的知识


1、volatile

1.1、volatile保证可见性

volatile可以保证,若一个线程改变了某块内存的值,其他线程是可见的,以至于其他线程能及时更新这块内存。

  • 线程拥有自己的内存空间:
    每个线程在运行时,都有自己的空间去加载缓存中的值,如果一个值发生改变,会先改变在线程中的值,再在一定时间内同步到缓存中。
    java中volatile关键字的作用_第1张图片

  • volatile可见性:
    当两个线程使用同一变量M时,线程1改变了M的值,如果不使用volatile,线程2可能感知不到M发生了改变,继续拿着M在缓存中的值运行。使用volatile的变量,在线程1改变M时,对其他线程来说就是可见的,就会去更新M的值。
    java中volatile关键字的作用_第2张图片

  • 其他发生内存刷新的情况:
    有些java代码是已经包含了刷新内存、内存同步的操作,这会使得一些变量不加volatile,也会在多线程中及时更新。例如:调用System.out.println()会刷新内存

1.2、volatile保证顺序性

volatile修饰的内存,可以(利用 jvm中的内存屏障)保证它在多个代码行中读写的执行是有顺序的。

1.2.1、重排序与内存屏障

  • 为什么会重排序?
    为了提高CPU效率,在结果一致性的前提下,在执行一些较为耗时的操作,CPU并不会空着等待它执行完毕再继续,而是继续执行下面的代码。
    java中volatile关键字的作用_第3张图片
  • 怎么阻止这种不按顺序执行的情况?
    如上图,在第二行和第三行之间加一条内存屏障指令,当机器读到内存屏障指令时,就知道要等上一行执行完,才能执行下一行。
    java中volatile关键字的作用_第4张图片

内存屏障有cpu级别的和jvm级别的,cpu级别靠汇编语言特有的指令实现

1.2.2、jvm中的内存屏障

jvm规范规定,jvm必须实现的4中屏障:LL、LS、SL、SS

L (Load) ,指的是从内存中读一个数据到CPU
S (Store),指的是从CPU中写一个数据到内存

LL指第一行是从内存中读一个数据到CPU,第二行也是从内存中读一个数据到CPU,中间加的内存屏障类型就叫LoadLoadBarrier

LS指第一行是从内存中读一个数据到CPU,第二行从CPU中写一个数据到内存,中间加的内存屏障类型就叫LoadStoreBarrier

面试题:DCL单例加不加volatile

DCL单例(Double Check Lock 双检查加锁机制的单例)

答案见 : 关于java中单例的几个疑问

你可能感兴趣的:(java系列,java,开发语言,经验分享)