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技术服务公司-木风未来科技-成都木风未来科技有限公司

相关推荐
tsyjjOvO12 小时前
JDBC(Java Database Connectivity)
java·数据库
qq_124987075312 小时前
基于springboot的尿毒症健康管理系统的设计与实现(源码+论文+部署+安装)
java·spring boot·spring·毕业设计·计算机毕业设计
黎子越13 小时前
python相关练习
java·前端·python
电商API&Tina13 小时前
电商数据采集 API 接口 全维度解析(技术 + 商业 + 合规)
java·大数据·开发语言·数据库·人工智能·json
liwulin050613 小时前
【JSON】使用com.fasterxml.jackson解析json字符串
java·数据库·json
what丶k14 小时前
深度解析:以Kafka为例,消息队列消费幂等性的实现方案与生产实践
java·数据结构·kafka
星火开发设计14 小时前
C++ 输入输出流:cin 与 cout 的基础用法
java·开发语言·c++·学习·算法·编程·知识
毕设源码-邱学长14 小时前
【开题答辩全过程】以 基于Springboot的酒店住宿信息管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
仟濹14 小时前
【Java加强】1 异常 | 打卡day1
java·开发语言·python
AllData公司负责人14 小时前
【亲测好用】实时开发平台能力演示
java·c语言·数据库