尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

第一次学 volatile 关键字,我看了三遍才搞懂它到底在干嘛

第一次学 volatile 关键字,我看了三遍才搞懂它到底在干嘛
📅 发布时间:2026/6/30 23:14:46

学 Java 并发编程的时候,第一个让我卡住的关键字就是 volatile。

网上搜了一圈,全是"可见性"“指令重排序”“内存屏障”——每个字都认识,放在一起我就不知道它们在说什么了。

说实话我看了好几遍,又去翻了点资料,总算理清楚了一点。这篇就当是我自己整理的学习笔记。可能有些地方说得不够严谨,但至少是我自己的理解。如果有哪里写错了,欢迎指出来,我也还在学。


先说 volatile 到底是干嘛的

volatile 是 Java 给变量加的一个关键字。

你不加它,变量在多线程下可能出问题。你加了它,就相当于告诉 JVM:“这个变量你给我小心点处理,别自作聪明。”

它主要做两件事。我分开来说。

第一件事:让一个线程改了,其他线程能看见

这个叫"可见性"。

我打个比方。假设你和几个同事一起做一个项目,项目文档放在共享文件夹里。但是每个人为了方便,都把文档在本地电脑打开了一份。现在你修改了文档,保存了。你的同事看自己本地那版——还是旧的内容。

这就是多线程里的问题。

Java 里每个线程都有自己的"工作内存",相当于本地缓存。线程读变量的时候,先读到自己这边来;改了之后,也不一定马上写回主内存。如果不用 volatile,别的线程可能根本看不到你改了。

加上 volatile 之后,Java 就会保证:你写的时候立即刷回主内存,别人读的时候直接从主内存读。相当于你在共享文档上点了"保存并同步",所有人都能看到最新版。

第二件事:不让编译器和处理器乱调顺序

这个叫"禁止指令重排序",比可见性难理解一点。

先说说指令重排序是怎么回事。

指令重排序是啥

编译器和处理器为了让程序跑得快一点,会在不改变执行结果的前提下,调整指令的执行顺序。

打个比方。你做番茄炒蛋,正常情况下应该是:洗番茄 → 切番茄 → 打蛋 → 炒菜。但如果你先打蛋再洗番茄,结果是一样的,没有人会在意你先做哪一步。编译器和处理器就是这个逻辑。

但这里有一个重要的前提:重排序不能影响单线程的运行结果。

所以 CPU 在做重排序的时候,它会盯着一个原则——数据依赖性。什么意思?就是如果两个操作之间有依赖关系,那就不能重排序。

我举个例子:

操作 A:x = 1 操作 B:y = 2 操作 C:z = x + y

操作 C 要用到 x 和 y 的值,所以它必须在 A 和 B 之后执行,这个顺序不会被打破。但是操作 A 和操作 B 之间没有依赖关系——谁先谁后无所谓,反正结果都是 x=1、y=2。所以编译器或者处理器完全可以把顺序调成 B 先执行、A 后执行。

这在单线程下没问题。但是在多线程环境下就不一定了——如果另一个线程在你改 x 和 y 的中间插了一脚,看到了一个"中间状态",可能就出问题了。

volatile 怎么管这件事

volatile 是靠"内存屏障"来管这件事的。

内存屏障这个东西,你可以把它理解成一道栅栏。编译器和处理器再怎么重排序,也不能把指令从栅栏的一边移到另一边去。

Java 针对 volatile 变量,在几个关键位置插了这些栅栏:

  • 写之前插一道:保证前面的普通写操作不会被排到 volatile 写之后
  • 写之后插一道:保证 volatile 写不会被排到后面的 volatile 读/写之后。这道屏障开销最大
  • 读之后插两道:保证 volatile 读不会被排到后面的普通读和普通写之后

说实话,记这些屏障的名字(StoreStore、StoreLoad、LoadLoad、LoadStore)对我来说意义不大。我更关心的是结果:加了 volatile,代码在多线程下就不会因为指令重排序而出一些莫名其妙的问题。

学完还是有点模糊的地方

写这篇的时候我又确认了一下自己的理解,发现有几个地方还是模棱两可的。

比如 volatile 和 synchronized 的区别。我知道 volatile 不能保证原子性——也就是说,如果你对一个 volatile 变量做 i++ 操作(读-改-写三步),它还是可能出问题。但具体到代码里什么时候用 volatile 什么时候用 synchronized,我还需要再多写几个例子才能有感觉。

还有一个让我纠结的点:volatile 的可见性。我看资料说它保证可见性,那是不是加了 volatile 就能保证线程安全了?不是的——刚才说了,它不保证原子性。这两个概念放在一起容易搞混,我也花了好一会儿才理清楚。

不过我觉得这就是学习的过程吧。先有个大概的框架,知道 volatile 能做什么、不能做什么,后面再慢慢往里面填细节。

简单总结一下我自己的理解

volatile 做两件事,不做第三件事:

  • 保证可见性:你改了,别人知道
  • 禁止重排序:不会乱调执行顺序
  • 不保证原子性:i++ 该出问题还是出问题

就这样。没什么花里胡哨的,记住它干什么不干什么,写代码的时候心里就有数了。


这篇是边学边写的。如果有理解不对的地方,欢迎指出来,我改。

相关新闻

  • E-Hentai下载器完整指南:如何轻松批量下载并打包图片资源
  • Ansible自动化运维实战:从入门到精通,轻松管理服务器集群
  • 如何快速部署Python自动化脚本:京东商品预约下单的完整解决方案

最新新闻

  • 这份大厂Java高频面试题(2026最新版),建议直接收藏
  • Meta Quest 播放软件《下一代视频播放器》NEXt-Gen Video Player 下载和使用教程
  • 【论文复现】存在测距误差的WSN无锚点分布式自定位,《WSN中存在测距误差的无锚点分布式自定位方法》
  • 抖音监控助手:实时追踪博主动态与直播推送的终极指南
  • VisualGGPK2完整指南:快速掌握《流放之路》游戏资源管理技巧
  • Spark SQL 优化:从 Catalyst 优化器到数据倾斜治理,大数据查询的性能调优路径

日新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号