当前位置: 首页 > backend >正文

【Java笔记】volatile 关键字

目录

    • 一、代码案例
    • 二、问题分析(重点)
    • 三、原因(Java层面)
    • 四:总结(记住)

一、代码案例

创建两个线程,第一个线程不停的循环去执行自己的任务,第二个线程输入一个停止标识使线程 1 退出

 public class Demo07_volatile {// 停止标识static int flag = 0;public static void main(String[] args) {// 创建执行任务的线程Thread t1 = new Thread(() -> {System.out.println(Thread.currentThread().getName() + "线程启动");while (flag == 0) {// 循环处理的任务}System.out.println(Thread.currentThread().getName() + "线程退出");}, "t1");// 启动线程 t1t1.start();// 创建线程 t2Thread t2 = new Thread(() -> {System.out.println(Thread.currentThread().getName() + "线程启动");Scanner scanner = new Scanner(System.in);System.out.println("请输入一个非 0 的整数");flag = scanner.nextInt();System.out.println(Thread.currentThread().getName() + "线程退出");}, "t2");// 启动线程 t2t2.start();}
}

正常来说,如果输入了一个非0整数,线程1会停止,但是事实并非如此,这个代码执行的结果是:

在这里插入图片描述
线程 t1 并没有退出。

二、问题分析(重点)

见下图,线程 t1 将主内存中的 flag 值读取到自己的工作内存(寄存器)中,此时,另外一个线程 t2 也将主内存中的 flag 值读取到自己的工作内存中,但是 t2 将 flag 值修改为了 1 ,重新写回了主内存中,但是对于线程 t1 来说,只是比较 flag 这个变量的值,从来没有修改过,所以 CPU 认为这个值永远不会改变,也不会从主内存重新读取值。这就出现了多线程环境下,一个线程修改了变量而另外一个线程无法感知到的情况,此时程序就会出现bug。因此,想要解决这个问题,最重要的就是当一个线程修改了另一个线程需要的变量,必须要让另一个线程感知到,也就是解决内存可见性问题。

在这里插入图片描述
但在 flag 变量前添加 volatile 关键字之后,线程 t2 修改 flag 值之后,线程 t1 关闭。

在这里插入图片描述

三、原因(Java层面)

加了 volatile 关键字的变量,前后都会加内存屏障,涉及到的读和写都是从主内存中获取,最终解决了内存可见性的问题。内存屏障的作用是保证指令执行的先后顺序,从而保证内存可见性。

volatile 写:
在这里插入图片描述

volatile 读:
在这里插入图片描述

四:总结(记住)

volatile 关键字从真正意义上解决了内存可见性的问题,用 volatile 修饰的变量,由于前后都有内存屏障,保证了指令的执行顺序,与 synchronized 不同,synchronized是通过原子性进而保证了内存可见性,也可以通过禁止指令重排序的方式解决有序性的问题,但是 volatile 不保证原子性。
一句话,volatile 解决了内存可见性,解决了有序性,不保证原子性
多个线程之间涉及的共享变量,如过存在修改的逻辑,只管加 volatile !!!

http://www.xdnf.cn/news/594.html

相关文章:

  • javaSE.四大函数式接口
  • Vue3基础
  • 关于一对多关系(即E-R图中1:n)中的界面展示优化和数据库设计
  • leetcode刷题日记——两数之和
  • Linux——firewalld防火墙
  • 2021-11-10 C++蜗牛爬井进3退1求天数
  • 【C++算法】63.字符串_二进制求和
  • 深度解析AI大模型中的模型微调技术:从基础到实践
  • 知识就是力量——一些硬件的使用方式
  • 第二十七讲:AI+农学导论
  • Python基于知识图谱的医疗问答系统【附源码、文档说明】
  • python基础知识点(3)
  • JAVA学习-多线程
  • linux查看目录相关命令
  • Linux系统中的网络传输、网络管理以及软件仓库的构建
  • @EnableAsync+@Async源码学习笔记之四
  • 2025年第十五届MathorCup数学应用挑战赛D题论文全网首发
  • MSCKF——运动方程IMU状态递推(Propagation)
  • 深度补全网络:CSPN++ 有哪些开源项目
  • 2025华中杯挑战赛B题【单车调度】原创论文讲解
  • docker 搭建nacos 2.2.1版本单机版
  • 国产SMT贴片机自主技术突破解析
  • A股周度复盘与下周策略 的deepseek提示词模板
  • Unreal 从入门到精通之如何接入MQTT
  • 【开发心得】Dify部署ollama模型的坑[8]
  • 【漫话机器学习系列】210.标准化(Standardization)
  • [Java · 初窥门径] Java 注释符
  • DEV-c++怎么免打头文件中英文切换
  • c语言中的原,反,补码
  • PyTorch 深度学习实战(38):注意力机制全面解析(从Seq2Seq到Transformer)