0

0

在Java中volatile关键字如何解决内存可见性问题_Java并发机制解析

P粉602998670

P粉602998670

发布时间:2026-02-11 03:49:19

|

470人浏览过

|

来源于php中文网

原创

volatile通过强制读写主内存和内存屏障保证可见性,但不保证原子性与有序性,无法替代synchronized实现线程安全计数器。

在java中volatile关键字如何解决内存可见性问题_java并发机制解析

volatile 怎么保证变量修改对其他线程立即可见

Java 中 volatile 关键字不加锁,但能强制线程每次读取都从主内存加载,每次写入都立刻刷回主内存。它绕过了 CPU 缓存(如 L1/L2)和寄存器缓存,直接走主存通路,从而避免一个线程改了值、另一个线程还在用旧缓存副本的情况。

典型场景是状态标志位:running 控制循环是否退出。若不用 volatile,JIT 可能将其优化为“本地寄存器常量”,导致 while 循环永远不退出。

  • 仅对单个变量生效,不能保证复合操作(如 i++)的原子性
  • 写操作会触发 StoreStore 和 StoreLoad 内存屏障,防止指令重排序影响可见性
  • 读操作插入 LoadLoad 和 LoadStore 屏障,确保后续读/写不会被提前到 volatile 读之前

哪些情况用 volatile 就够了,哪些一定不行

volatile 适合“一写多读”且写操作本身是原子的场景,比如开关控制、初始化完成标记、简单数值状态更新(前提是不依赖当前值)。

以下情况它完全无效:

立即学习Java免费学习笔记(深入)”;

  • counter++:读-改-写三步非原子,即使 countervolatile,仍可能丢失更新
  • 多个 volatile 变量之间存在逻辑依赖(如先设 ready = true 再设 data = 42),无法保证其他线程看到二者顺序一致
  • 需要 CAS 或条件等待(如 wait/notify)时,必须配合 synchronizedjava.util.concurrent 工具类

volatile 和 synchronized 在可见性上的本质区别

synchronized 的可见性保障来自“锁释放时将工作内存全部刷新到主内存,锁获取时清空本地工作内存并从主内存重读”。它作用于整个临界区,天然包含原子性和有序性。

ChatGPT Website Builder
ChatGPT Website Builder

ChatGPT网站生成器,AI对话快速生成网站

下载

volatile 则轻量得多,只针对单个变量,不阻塞线程,也不提供互斥——它解决的是“能不能看到最新值”,而不是“能不能同时改”。

  • 性能上,volatile 读几乎无开销;写比普通变量略重(因内存屏障),但远低于锁竞争
  • JVM 对 volatile 字段的优化非常有限:禁止指令重排序、禁止寄存器缓存、禁止常见编译器优化(如公共子表达式消除)
  • 注意:在 Java 5 之前,volatile 不保证有序性(如 double/long 的 64 位写可能被拆成两个 32 位写),现在已修复

为什么 volatile 不能替代 synchronized 实现线程安全计数器

看这个例子:volatile int count = 0;,然后 100 个线程各执行 100 次 count++。最终结果大概率小于 10000。

原因在于:每次 count++ 实际分三步——读 count 值 → 加 1 → 写回。即使每一步的读/写都经过主内存,两个线程仍可能同时读到相同旧值(比如都是 99),各自加 1 后都写回 100,导致一次更新丢失。

  • 要真正线程安全,要么用 AtomicInteger.incrementAndGet()(底层 CAS + volatile)
  • 要么用 synchronized(this) { count++; }
  • 要么用 ReentrantLock 包裹

volatile 本身不提供“比较并交换”或“临界区排他”能力,这是它最常被误用的地方。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1547

2023.10.24

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.11.20

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

101

2023.09.25

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

688

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

557

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

206

2025.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.08.29

2026春节习俗大全
2026春节习俗大全

本专题整合了2026春节习俗大全,阅读专题下面的文章了解更多详细内容。

68

2026.02.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3.5万人学习

C# 教程
C# 教程

共94课时 | 9.2万人学习

Java 教程
Java 教程

共578课时 | 63.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号