news 2026/10/13 13:12:25

Java中为什么volatile不能解决多写问题?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java中为什么volatile不能解决多写问题?

上述规约是一个关于Java并发编程的重要问题。本篇博文我来详细解释一下:

1.volatile的内存可见性

volatile的作用:

  • 保证可见性:当一个线程修改了volatile变量的值,新值会立即刷新到主内存,其他线程读取时会从主内存重新获取最新值
  • 禁止指令重排序:防止JVM的指令重排序优化

示例:

publicclassVolatileExample{privatevolatilebooleanflag=false;publicvoidwriter(){flag=true;// 写操作}publicvoidreader(){if(flag){// 读操作// 一定能看到最新值}}}

2.为什么volatile不能解决多写问题

publicclassCounter{privatevolatileintcount=0;// 多线程调用会有问题publicvoidincrement(){count++;// 不是原子操作:读→改→写}}

问题分析:

线程A:读取count=0 线程B:读取count=0 线程A:count+1=1,写回 线程B:count+1=1,写回 // 结果应该是2,实际是1

3.解决方案对比

方案1:AtomicInteger

importjava.util.concurrent.atomic.AtomicInteger;publicclassAtomicExample{privateAtomicIntegercount=newAtomicInteger(0);publicvoidincrement(){count.incrementAndGet();// 原子操作}publicintget(){returncount.get();}}

原理:基于CAS(Compare And Swap)

publicfinalintincrementAndGet(){returnunsafe.getAndAddInt(this,valueOffset,1)+1;}// 实际是自旋CAS操作

方案2:LongAdder(JDK8+推荐)

importjava.util.concurrent.atomic.LongAdder;publicclassLongAdderExample{privateLongAddercount=newLongAdder();publicvoidincrement(){count.increment();// 性能更好}publiclongsum(){returncount.sum();}}

4.性能对比分析

特性AtomicLongLongAdder
原理CAS自旋分段CAS
高并发写性能一般优秀
读性能O(1)O(N)需要合并
内存占用低较高
适用场景读写均衡写多读少

5.完整示例

importjava.util.concurrent.atomic.AtomicInteger;importjava.util.concurrent.atomic.LongAdder;importjava.util.concurrent.CountDownLatch;publicclassCounterComparison{// 方案1:volatile(不安全)privatevolatileintvolatileCount=0;// 方案2:AtomicIntegerprivateAtomicIntegeratomicCount=newAtomicInteger(0);// 方案3:LongAdder(JDK8+推荐)privateLongAdderadderCount=newLongAdder();publicvoidtestVolatile()throwsInterruptedException{CountDownLatchlatch=newCountDownLatch(100);for(inti=0;i<100;i++){newThread(()->{for(intj=0;j<1000;j++){volatileCount++;// 线程不安全}latch.countDown();}).start();}latch.await();System.out.println("Volatile结果(可能不正确): "+volatileCount);}publicvoidtestAtomic()throwsInterruptedException{CountDownLatchlatch=newCountDownLatch(100);for(inti=0;i<100;i++){newThread(()->{for(intj=0;j<1000;j++){atomicCount.incrementAndGet();}latch.countDown();}).start();}latch.await();System.out.println("AtomicInteger结果: "+atomicCount.get());}publicvoidtestLongAdder()throwsInterruptedException{CountDownLatchlatch=newCountDownLatch(100);for(inti=0;i<100;i++){newThread(()->{for(intj=0;j<1000;j++){adderCount.increment();}latch.countDown();}).start();}latch.await();System.out.println("LongAdder结果: "+adderCount.sum());}publicstaticvoidmain(String[]args)throwsInterruptedException{CounterComparisontest=newCounterComparison();test.testAtomic();test.testLongAdder();test.testVolatile();}}

6.使用建议

  1. 单写多读:使用volatile
  2. 低竞争环境:使用AtomicInteger/AtomicLong
  3. 高并发写场景:使用LongAdder(JDK8+)
  4. 精确统计场景:使用Atomic系列(LongAdder的sum()可能不是实时精确值)

总结

  • volatile只解决可见性问题,不解决原子性问题
  • 对于count++这类复合操作,必须使用原子类
  • 在JDK8+的高并发写场景下,LongAdder性能通常优于AtomicLong
  • 选择哪个工具取决于具体的读写比例和并发程度
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 12:54:15

【开题答辩全过程】以 基于Java的黑豆奶牛养殖基地系统的设计与实现为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

作者头像 李华
网站建设 2026/10/12 22:03:32

YOLO目标检测支持角色权限?不同用户访问GPU资源

YOLO目标检测支持角色权限&#xff1f;不同用户访问GPU资源 在智能制造工厂的视觉质检线上&#xff0c;一台边缘服务器正同时为三个团队提供YOLO目标检测服务&#xff1a;质量部门用它识别产品划痕&#xff0c;物流组依赖其统计包装数量&#xff0c;而安全监控系统则靠它追踪人…

作者头像 李华
网站建设 2026/10/7 9:01:49

Stage转换的TaskSet中Task个数由什么决定

在分布式计算框架中&#xff0c;一个Stage内的TaskSet包含的Task个数主要由以下因素决定&#xff1a;当前Stage对应的RDD分区数每个Task负责处理一个RDD分区&#xff08;Partition&#xff09;。例如&#xff1a;val rdd sc.parallelize(1 to 100, 10) // 创建10个分区的RDD v…

作者头像 李华
网站建设 2026/10/13 11:38:27

YOLO目标检测支持字段投影?减少GPU数据传输

YOLO目标检测支持字段投影&#xff1f;减少GPU数据传输 在智能工厂的质检流水线上&#xff0c;摄像头每秒捕捉数百帧高清图像&#xff0c;YOLO模型飞速识别缺陷产品。但你是否想过——这些画面中真正需要分析的区域&#xff0c;可能只占整个画面的不到30%&#xff1f;其余部分&…

作者头像 李华
网站建设 2026/10/13 11:39:03

YOLO模型支持OpenVINO?Intel GPU部署指南

YOLO模型支持OpenVINO&#xff1f;Intel GPU部署指南 在智能制造车间的高速流水线上&#xff0c;每分钟数百件产品飞速流转&#xff0c;视觉系统必须在毫秒级内完成缺陷检测并触发分拣动作。传统基于CPU的目标检测方案常常因延迟过高而错过关键帧&#xff0c;导致漏检率上升&am…

作者头像 李华
网站建设 2026/10/13 11:39:59

YOLO开源项目贡献指南:提交代码前先用GPU测试

YOLO开源项目贡献指南&#xff1a;提交代码前先用GPU测试 在现代计算机视觉开发中&#xff0c;向主流目标检测框架如YOLO提交代码&#xff0c;早已不是“写完能跑”那么简单。尤其当你修改的是模型结构、训练逻辑或数据流时&#xff0c;一个看似无害的改动——比如忘记把某个张…

作者头像 李华