一、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{
v=this.getIntVolatile(o,offset);
//2.执行CAS:比较并交换
}while(!this.compareAndSwapInt(o,offset,v,v+delta));
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竞争
ThreadLocalRandom.current().nextInt();
LongAdderadder=newLongAdder();
adder.add(1);
//可参考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,理解其优缺点,并能够根据具体场景选择合适的并发工具。