德阳市网站建设_网站建设公司_Linux_seo优化
2026/3/2 17:06:35 网站建设 项目流程

上述规约是一个关于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
  • 选择哪个工具取决于具体的读写比例和并发程度

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询