【多线程】volatile

目录

一、jvm 内存模型

二、volatile 的作用

三、volatile 的特点

四、volatile 的实现原理

4.1 内存屏障


一、jvm 内存模型

在理解 volatile 之前,先要了解 jvm 内存模型

  【多线程】volatile_第1张图片

如上图所示,有几个关键点:

  • 所有线程的共享变量都存储在主内存中,每个线程都有一个专属于自己的工作内存,每个线程都不会直接操作主内存中的变量,而是将主内存上的变量放进自己的工作内存中,只操作工作内存的数据。
  • 当对工作内存修改完毕后,再将修改后的结果放回到主内存中。
  • 每个线程都只能操作自己工作内存中的变量,无法直接访问其他工作内存的变量
  • 线程间的变量传值只能依赖主内存完成

 

二、volatile 的作用

volatile 是一个修饰词,翻译为不稳定的,当一个变量被修饰后,有两个作用:

保证可见性

保证线程更新变量后能立刻被其他线程读到,用于保证线程读到的变量一定是最新的。

内部原理为线程修改了自己工作内存的变量后,会被立即将结果刷新会主内存中。同时其他线程读到该变量的值也作废,强制重新从主内存中读取该变量的值。

● 禁止进行指令重排序

每一行代码的执行顺序并不一定按照我们编写的顺序执行,为了提高执行效率,JVM 和 CPU 会对指令进行重新排序。而 volatile 会禁止 jvm 和 cpu 对其修饰的变量进行重排序

举个栗子

面包工坊做面包,按顺序是做好一个面包,然后将面包放进烤炉烤。而经过优化,变成先做完一批面包,再一起放入烤炉。如果将做面包的过程改为定义对象,将烤制的过程比作对象实例化,就可以节省大量的资源

 

三、volatile 的特点

无法保证原子性

即对 volatile 修饰的变量进行操作,无法保证多线程的安全,volatile 只负责保证被操作变量的原子性

 可见性

即当多个线程访问同一个变量时,能够保证任意线程修改了变量的值,其他线程立即能够看到和使用修改的值

 有序性

即程序执行的顺序按照代码的先后顺序执行,最有名的例子就是单例模式中的双重检查锁

public class Singleton {
    // singleton 作为
    public static volatile Singleton singleton;

    private Singleton() {};

    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (singleton) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

 

四、volatile 的实现原理

volatile 能够禁止指令排序,其实是通过内存屏障来实现的

4.1 内存屏障

内存屏障其实是一种 JVM 指令,Java 内存模型的重排规则会要求 Java 编译器在生成 JVM 指令时插入特定的内存屏障指令,通过这些内存屏障指令来禁止特定的指令重排序。

https://juejin.im/post/6844903945299558414

 

 

 

 

 

你可能感兴趣的:(Java,多线程,java)