【JUC并发编程】volitale 关键字
创始人
2024-05-29 02:51:35
0

一、 背景 —— 什么是 JMM

JMM 是 Java 内存模型的缩写,其将 Java 运行的底层内存模型抽象成了 主存 和 工作内存。 其中, 主存就是线程共享的内存, 工作内存就是线程所私有的内存 。

二、什么是可见性

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

但是由于 JIT (即时编译器)的存在,有时我们放在主存中内容,会被其移动到工作内存给某个线程私有 。(嘤嘤嘤, 不能怪 JIT 鸭 ~ 它也是为了优化程序执行的效率,它也不知道不能移鸭 ~)

三、引出 volitale

1. volatile 用来做什么

volatile 用于保证我们某个变量的可见性,使其一直存放在主存中,不被移动到某个线程的私有工作内存中。 (synchronized 也能实现可见性,但是麻烦,没有 volatile 简洁,而且更加重量级,会降低效率)

2. 举个例子,怎么使用

volatile 可以用来修饰 :

  1. 成员变量
  2. 静态成员变量

使用实例

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 可能对指令进行重排序,重排序可以会在多线程并发时出现问题)

在这里插入图片描述

上一篇:自动化测试

下一篇:如何写好单测

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...