Java回顾---原子操作类

从JDK1.5开始,Java为我们提供的一系列的原子处理类:AtomicBoolean、AtomicInteger、AtomicLong等等,主要用在高并发的场景下高效处理程序,为我们简化同步处理。

我们以AtomicInteger举例:

AtomicInteger是一个提供原子操作的Integer类,在Java中,++i和i++并不是线程安全的,在使用的时候我们不可避免的使用synchronized关键字进行加锁操作。但是AtomicInteger则提供了一种线程安全的操作接口:

public final int get() //获取当前的值
public final int getAndSet(int newValue) //获取当前的值,并设置新的值
public final int getAndIncrement() //获取当前的值,并自增
public final int getAndDecrement() //获取当前的值,并自减
public final int getAndAdd(int delta) //获取当前的值,并加上预期的值

使用了AtomicInteger之后,我们就没有必要给数值的操作加锁了,这样在非激烈竞争的情况下,开销更小,速度更快。

AtomicInteger本质上是通过CAS实现的,它里面主要维护了三个变量:

  • unSafe:Java提供的获得对对象内存地址访问的类
  • valueOffset:value本身在内存地址的偏移量,为了方便找到保存数据的地址,方便进行比较
  • value:存储的值,该属性借助volatile保证其在线程间是可见的

我们查看AtomicInteger的自增函数incrementAndGet()的源码时,发现自增函数底层调用的是unsafe.getAndAddInt()。

// ------------------------- JDK 8 -------------------------
// AtomicInteger 自增方法
public final int incrementAndGet() {
  return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}

// Unsafe.class
public final int getAndAddInt(Object var1, long var2, int var4) {
  int var5;
  do {
      var5 = this.getIntVolatile(var1, var2);
  } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
  return var5;
}

// ------------------------- OpenJDK 8 -------------------------
// Unsafe.java
public final int getAndAddInt(Object o, long offset, int delta) {
   int v;
   do {
       v = getIntVolatile(o, offset);
   } while (!compareAndSwapInt(o, offset, v, v + delta));
   return v;
}

getAndAddInt()循环获取给定对象o中的偏移量处的值v,然后判断内存值是否等于v。如果相等则将内存值设置为 v + delta,否则返回false,继续循环进行重试,直到设置成功才能退出循环,并且将旧值返回。整个“比较+更新”操作封装在compareAndSwapInt()中,在JNI里是借助于一个CPU指令完成的,属于原子操作,可以保证多个线程都能够看到同一个变量的修改值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值