并发编程-Volatile

申明:文章内容是本人学习极客时间课程所写,作为笔记进行记录,文字和图片基本来源于课程资料,在某些地方会插入一点自己的理解,未用于商业用途,侵删。
原资料地址:课程资料

什么是Volatile

volatile可以保证多线程场景下变量的可见性和有序性。如果某变量用volatile修饰,则可以确保所有线程看到变量的值是一致的。

可见性:保证此变量的修改对所有线程的可见性。
有序性:禁止指令重排序优化,编译器和处理器在进行指令优化时,不能把在volatile变量操作(读/写)后面的语句放到其前面执行,也不能将volatile变量操作前面的语句放在其后执行。遵循了JMM的happens-before规则。

线程写volatile变量的过程:

  1. 改变线程本地内存中volatile变量副本的值;
  2. 将改变后的副本的值从本地内存刷新到主内存
    线程读volatile变量的过程:
  3. 从主内存中读取volatile变量的最新值到线程的本地内存中
  4. 从本地内存中读取volatile变量的副本

Volatile的原理

volatile实现内存可见性原理:内存屏障(Memory Barrier)

内存屏障(Memory Barrier)是一种CPU指令,用于控制特定条件下的重排序和内存可见性问题。Java
编译器也会根据内存屏障的规则禁止重排序

写操作时,通过在写操作指令后加入一条store屏障指令,让本地内存中变量的值能够刷新到主内存中
读操作时,通过在读操作前加入一条load屏障指令,及时读取到变量在主内存的值

Java编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。为保证在任意处理器平台下能得到正确的 volatile 内存操作语义,JMM 采取保守策略,下面是基于保守策略的
JMM 内存屏障插入策略:

  • 在每个 volatile 写前,插入StoreStore 屏障。
  • 在每个 volatile 写后,插入StoreLoad 屏障。
  • 在每个 volatile 读后,插入LoadLoad 屏障。
  • 在每个 volatile 读后,插入LoadStore 屏障。
    并发编程-Volatile_第1张图片
    是否从排序:
    并发编程-Volatile_第2张图片

Volatile的缺陷

原子性的问题:虽然volatile可以保证可见性,但是不能满足原子性,也就是说存在线程安全问题。

你可能感兴趣的:(Java,多线程与并发,java,jvm,开发语言)