JavaAtomicInteger底层实现深度解析

一、AtomicInteger核心概述

`java.util.concurrent.atomic.AtomicInteger`是JUC包下的原子整型类,其底层核心实现基于:CAS无锁算法+volatile关键字,实现对整型变量的原子性读写操作,全程无锁,是轻量级的并发安全解决方案。

为什么需要AtomicInteger?

普通`intcount++`看似一行代码,实际包含3个CPU指令:

1.读取变量当前值到寄存器

2.对读取到的值执行+1运算

3.将运算后的新值写回变量

在多线程并发执行时,会出现线程安全问题(值覆盖问题)。常规加锁方案(synchronized/ReentrantLock)有性能开销,而AtomicInteger采用无锁方式实现原子更新,并发性能更高。

二、核心技术支撑

1.volatile关键字保证可见性+有序性

```java

publicclassAtomicIntegerextendsNumberimplementsjava.io.Serializable{

//核心存储变量:用volatile修饰

privatevolatileintvalue;

//内存偏移量

privatestaticfinallongvalueOffset;

//Unsafe实例

privatestaticfinalUnsafeunsafe=Unsafe.getUnsafe();

static{

try{

//初始化value的内存偏移量

valueOffset=unsafe.objectFieldOffset

(AtomicInteger.class.getDeclaredField("value"));

}catch(Exceptionex){thrownewError(ex);}

}

}

``

volatile作用:

可见性:一个线程修改value后,其他线程立即看到最新值

有序性:禁止指令重排序

不保证原子性:需要配合CAS使用

2.CAS算法保证操作原子性

CAS(CompareAndSwap):比较并交换,CPU提供的原子指令

核心三要素:内存地址V、预期值A、新值B

核心逻辑:

1.比较内存地址V中的实际值是否等于预期值A

2.如果相等,将内存地址V的值更新为新值B,返回成功

3.如果不相等,不做更新,返回失败

AtomicInteger中的CAS调用:

```java

//Unsafe类中的CAS本地方法

publicfinalnativebooleancompareAndSwapInt(

Objectvar1,//要操作的对象

longvar2,//对象中变量的内存偏移量(valueOffset)

intvar4,//预期值A

intvar5//新值B

);

```

三、源码级执行流程分析

1.getAndIncrement()方法(等价于count++)

```java

publicfinalintgetAndIncrement(){

//调用Unsafe的getAndAddInt

returnunsafe.getAndAddInt(this,valueOffset,1);

}

//Unsafe类中的实现

publicfinalintgetAndAddInt(Objecto,longoffset,intdelta){

intv;

//自旋(死循环)+CAS

do{

//1.获取变量的最新值作为预期值A

v=this.getIntVolatile(o,offset);

//2.执行CAS:比较并交换

}while(!this.compareAndSwapInt(o,offset,v,v+delta));

//3.返回更新前的旧值

returnv;

}

```

2.compareAndSet()方法

```java

publicfinalbooleancompareAndSet(intexpect,intupdate){

//直接调用CAS本地方法

returnunsafe.compareAndSwapInt(this,valueOffset,expect,update);

}

```

3.执行流程总结

以`getAndIncrement()`为例:

1.自旋(死循环):线程不断获取变量的最新值作为预期值

2.CAS尝试更新:比较内存中的实际值和预期值

一致则更新,返回成功

不一致则重新自旋,直到更新成功

四、CAS的三大缺点(高频追问)

1.ABA问题

问题描述:值从A→B→A,CAS认为没有被修改过,实际已被修改两次

影响场景:链表、栈、队列等数据结构操作

解决方案:使用带版本号的原子类

```java

//使用AtomicStampedReference解决ABA问题

AtomicStampedReference<IntegeratomicStampedRef=

newAtomicStampedReference<(100,0);

//CAS时比较值和版本号

atomicStampedRef.compareAndSet(100,101,0,1);

```

2.自旋导致的CPU空转

问题描述:高并发竞争激烈时,大量线程自旋重试,CPU使用率飙升

解决方案:

低并发场景用CAS

高并发场景用锁(synchronized/ReentrantLock)

JDK1.8后synchronized优化,性能差距不大

3.只能保证单个变量的原子性

问题描述:无法实现多个变量的复合原子操作

解决方案:多变量操作使用锁

五、AtomicIntegervssynchronized性能对比

|----------|----------------------------|-----------------|
| 场景 | 推荐方案 | 原因 |
| 低并发、竞争少 | AtomicInteger | 无锁、无上下文切换、性能高 |
| 高并发、竞争激烈 | synchronized | 避免CPU空转、锁升级机制稳定 |
| 简单单变量操作 | AtomicInteger | 代码简洁、性能好 |
| 复杂多变量操作 | synchronized/ReentrantLock | 保证复合操作的原子性 |

AtomicInteger基于无锁CAS实现,低竞争时性能极高;synchronized基于锁实现,高竞争时性能更稳定。开发中根据并发场景选型:简单的单变量原子更新用AtomicInteger,复杂的多变量复合操作或高竞争场景用synchronized/ReentrantLock。

六、手写简易AtomicInteger

```java

/

手写简易版AtomicInteger

/

publicclassMyAtomicInteger{

//用volatile保证可见性和有序性

privatevolatileintvalue;

publicMyAtomicInteger(intinitialValue){

this.value=initialValue;

}

//获取当前值

publicintget(){

returnvalue;

}

//原子性自增,等价于count++

publicintgetAndIncrement(){

intexpect;

intupdate;

//自旋+CAS

do{

expect=get();

update=expect+1;

//模拟CAS操作

}while(!compareAndSwap(expect,update));

returnexpect;

}

//核心CAS方法

privatebooleancompareAndSwap(intexpect,intupdate){

//如果内存值等于预期值,更新为新值

if(this.value==expect){

this.value=update;

returntrue;

}

returnfalse;

}

/ /测试

publicstaticvoidmain(String[]args)throwsInterruptedException{

MyAtomicIntegercount=newMyAtomicInteger(0);

//多线程测试

Thread[]threads=newThread[1000];

for(inti=0;i<1000;i++){

threads[i]=newThread((){

for(intj=0;j<1000;j++){

count.getAndIncrement();

}

});

threads[i].start();

}

//等待所有线程完成

for(Threadt:threads){

t.join();

}

System.out.println("最终结果:"+count.get());//应该是1000000

}

}

``

七、实战建议

1.选型指南

简单计数器:使用AtomicInteger

高并发计数器:使用LongAdder

需要解决ABA问题:使用AtomicStampedReference

多变量原子操作:使用synchronized或ReentrantLock

2.性能优化

```java

//优化:减少CAS竞争

//1.使用线程局部变量

ThreadLocalRandom.current().nextInt();

//2.使用LongAdder替代AtomicLong

LongAdderadder=newLongAdder();

adder.add(1);

//3.合理控制自旋次数

//可参考JDK的LockSupport.parkNanos()

```

3.监控与调试

```java

//监控CAS成功/失败率

AtomicIntegersuccess=newAtomicInteger();

AtomicIntegerfailure=newAtomicInteger();

//在CAS操作前后统计

if(atomicInteger.compareAndSet(expected,newValue)){

success.incrementAndGet();

}else{

failure.incrementAndGet();

}

```

总结

AtomicInteger的底层实现是Java并发编程的基础知识点,掌握其原理不仅有助于面试,更能帮助在实际开发中做出合理的技术选型。记住核心:CAS+volatile,理解其优缺点,并能够根据具体场景选择合适的并发工具。

来源:小程序app开发|ui设计|软件外包|IT技术服务公司-木风未来科技-成都木风未来科技有限公司

相关推荐
BD_Marathon2 小时前
搭建MyBatis框架之创建MyBatis的映射文件(五)
java·数据库·mybatis
一只叫煤球的猫2 小时前
为什么Java里面,Service 层不直接返回 Result 对象?
java·spring boot·面试
洛阳泰山2 小时前
智能体项目MaxKB4J - 本地部署与开发完整指南
java·agent·工作流·rag·智能体·maxkb
Solar20252 小时前
机械制造业TOB企业获客软件选型指南:从挑战到解决方案的深度解析
java·大数据·服务器·架构·云计算
星火开发设计2 小时前
C++ stack 全面解析与实战指南
java·数据结构·c++·学习·rpc··知识
宋情写2 小时前
JavaAI06-SpringAI
java·人工智能
Hello.Reader2 小时前
Flink Avro Format Java / PyFlink 读写、Schema 细节与坑点总结
java·python·flink
人道领域3 小时前
【零基础学java】(反射)
java·开发语言
C雨后彩虹3 小时前
书籍叠放问题
java·数据结构·算法·华为·面试