Java并发编程中的volatile关键字详解

 更新时间:2023年08月14日 08:29:24   作者:刘婉晴  
这篇文章主要介绍了Java并发编程中的volatile关键字详解,volatile 用于保证我们某个变量的可见性,使其一直存放在主存中,不被移动到某个线程的私有工作内存中,需要的朋友可以参考下

一、什么是 JMM

JMM 是 Java 内存模型的缩写,其将 Java 运行的底层内存模型抽象成了 主存 和 工作内存。

其中, 主存就是线程共享的内存, 工作内存就是线程所私有的内存 。

二、什么是可见性

可见性是指放在主存中的内容所有线程都是可见的 。

但是由于 JIT (即时编译器)的存在,有时我们放在主存中内容,会被其移动到工作内存给某个线程私有 。

三、引出 volitale

1. volatile 用来做什么

volatile 用于保证我们某个变量的可见性,使其一直存放在主存中,不被移动到某个线程的私有工作内存中。

synchronized 也能实现可见性,但是麻烦,没有 volatile 简洁,而且更加重量级,会降低效率

2. 举个例子,怎么使用

volatile 可以用来修饰 :

  • 成员变量
  • 静态成员变量

使用实例

public class TestVolatile {
     volatile static boolean use = true;
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (use){
                // 执行相应操作
            }
        });
        thread.start();
        // 主线程休眠一秒
        sleep(1000);
        use = false;
    }
}

3. volatile 可以保证原子性嘛

不能,它只能保证可见性,不能保证原子性 。

四、 volatile 原理 (JDK 1.5 之后)

内存屏障技术, Memory Barrier

  • 写指令,加入写屏障
  • 读指令,加入读屏障

1. 保证可见性

  • 写屏障保证在该屏障之前,对共享变量的改动,都同步到主存中
  • 读屏障保证在该屏障之后,对共享变量的读取,加载的是主存中的最新数据

在这里插入图片描述

2. 保证有序性

  • 写屏障确保指令重排时,不会将写屏障之前的代码排在写屏障之后
  • 读屏障确保指令重排时,不能将读屏障之前的代码排在读屏障之后

3. 解决 dcl 问题 (double-checked locking)

public class Singleton {
    private Singleton() {}
    private static Singleton INSTANCE = null;
    public static Singleton getINSTANCE(){
        if(INSTANCE == null){
            synchronized (Singleton.class) {
                if(INSTANCE == null) {
                	// 会因为指令重排序出现问题
                    INSTANCE = new Singleton();
                }
            }
        }
        return INSTANCE;
    }
}

解决 dcl 问题

为共享变量加上 volatile 关键字,从而避免指令重排序的问题 。 (jvm 可能对指令进行重排序,重排序可以会在多线程并发时出现问题)

在这里插入图片描述

到此这篇关于Java并发编程中的volatile关键字详解的文章就介绍到这了,更多相关Java中的volitale关键字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring中@PropertySource的使用方法和运行原理详解

    Spring中@PropertySource的使用方法和运行原理详解

    这篇文章主要介绍了Spring中@PropertySource的使用方法和运行原理详解,PropertySource注解可以方便和灵活的向Spring的环境容器(org.springframework.core.env.Environment Environment)中注入一些属性,这些属性可以在Bean中使用,需要的朋友可以参考下
    2023-11-11
  • Java递归 遍历目录的小例子

    Java递归 遍历目录的小例子

    Java递归 遍历目录的小例子,需要的朋友可以参考一下
    2013-03-03
  • SpringBoot整合Security权限控制登录首页

    SpringBoot整合Security权限控制登录首页

    这篇文章主要为大家介绍了SpringBoot整合Security权限控制登录首页示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Java枚举类型enum的详解及使用

    Java枚举类型enum的详解及使用

    这篇文章主要介绍了Java枚举类型enum的详解及使用的相关资料,需要的朋友可以参考下
    2017-05-05
  • mybatis单笔批量保存实体数据的方法

    mybatis单笔批量保存实体数据的方法

    这篇文章主要介绍了mybatis单笔批量保存实体数据的相关知识,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-01-01
  • Knife4j 3.0.3 整合SpringBoot 2.6.4的详细过程

    Knife4j 3.0.3 整合SpringBoot 2.6.4的详细过程

    本文要讲的是 Knife4j 3.0.3 整合SpringBoot 2.6.4,在SpringBoot 2.4以上的版本和之前的版本还是不一样的,这个也容易导致一些问题,本文就这两个版本的整合做一个实战介绍
    2022-09-09
  • 详解SpringBoot 解决拦截器注入Service为空问题

    详解SpringBoot 解决拦截器注入Service为空问题

    这篇文章主要介绍了详解SpringBoot 解决拦截器注入Service为空问题的解决,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • 图文详解JAVA实现哈夫曼树

    图文详解JAVA实现哈夫曼树

    所谓哈夫曼树就是要求最小加权路径长度,这是什么意思呢?简而言之,就是要所有的节点对应的路径长度(高度-1)乘以该节点的权值,然后保证这些结果之和最小。下面这篇文章就给大家详细介绍
    2016-08-08
  • Java实现监听文件变化的三种方案详解

    Java实现监听文件变化的三种方案详解

    这篇文章主要介绍了Java实现监听文件变化的三种方法,每种方案给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • JAVA正则表达式过滤文件的实现方法

    JAVA正则表达式过滤文件的实现方法

    这篇文章主要介绍了JAVA正则表达式过滤文件的实现方法的相关资料,希望通过本文大家能够掌握理解这部分内容,需要的朋友可以参考下
    2017-09-09

最新评论