在JDK1.5开始,AtomicInteger中就基于CAS原理做了相关操作。
public static void main(String[] args) throws Exception{
//初识值为0
AtomicInteger atomicInteger = new AtomicInteger();
//查看当前对象的值
System.out.println("初始值:"+atomicInteger.get());
//给对象当前值加1并返回该值
atomicInteger.incrementAndGet();
//查看当前对象的值
System.out.println("当前值:"+atomicInteger.get());
}
运行结果:
点击incrementAndGet()进去查看
我们先查看方法中如何定义unsafe、valueOffset这两个变量
private static final long valueOffset;
static {
try {
//获取值value在这个对象内存中的起始位置
//对象可以具象理解为jvm中的一段内存,对象中的属性信息在这段内存中都是有序排列的,该方法呢就是获取value在这段内存中的起始位置
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
现在查看 incrementAndGet()的具体实现
/**
* var1:当前对象
* var2:对象中value在对象内存中的起始位置
* var4:固定值 1
**/
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
//获取当前对象的value值
var5 = this.getIntVolatile(var1, var2);
//比较获取的值var5和对象现在的值是否相同(防止当前该值已经被其他线程修改)
//不同==>继续获取对象的最新value然后进行比较(自旋)
//相同==>将对象的value改成var5 + var4(对象的值+1),并返回刚才获取的var5
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
进一步查看一眼compareAndSwapInt(Object var1, long var2, int var4, int var5)
在返回看AtomicInteger.incrementAndGet()的方法
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final int incrementAndGet() {
//unsafe.getAndAddInt(this, valueOffset, 1):获取对象当前的值
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
以上是JDK1.5后java对CAS使用的一个基础案例
compareAndSwapInt(Object var1, long var2, int var4, int var5)由于是用native修饰的暂时没有进一步追踪,后查阅资料了解到其底部是通过已经汇编指令执行的 ==> lock cmpxchg 指令
//在实际让对象的值改变前判断系统是否是多核的
//是 ==》 指令前添加lock(锁)执行
//不是==》直接执行指令
lock cmpxchg 指令
//cmpxchg = cas修改变量值