JAVA并发编程---AtomicLong类

讲AtomicLong类之前先得讲解下CAS操作
什么时CAS:JDK提供的非阻塞原子性操作,它通过硬件保证了比较-更新的原子性
主要方法:boolean compareAndSwapLong(Object obj,long value,long expect,long update)
四个操作数为:对象的内存地址,对象中的变量的偏移量,变量的预期值,新值。
操作含义:如果对象obj中内存偏移量为valueOffset的变量值为expect,则使用新值update替换旧值。

来看AtomicLong类

public class AtomicLong extends Number implements java.io.Serializable {
 	private static final long serialVersionUID = 1927816293512124184L;
 	
	 private static final Unsafe unsafe = Unsafe.getUnsafe();
	 
	 // 保存AtomicLong中value的内存地址便于快速操作
	 private static final long valueOffset;
	 
	static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
	
	private static native boolean VMSupportsCS8();

	// 获取value的内存地址的逻辑操作
	static {
   	 try {
       	 valueOffset = unsafe.objectFieldOffset
     	     	  (AtomicLong.class.getDeclaredField("value"));
  	 	 } catch (Exception ex) { throw new Error(ex); }
	}

	 private volatile long value;

	 // 以initialValue对value进行初始化
	public AtomicLong(long initialValue) {
 	   value = initialValue;
	}

	// 以默认值0对value进行初始化
  	public AtomicLong() {
	 } }

AtomicLong类的get动作包括直接返回值和返回值后自增自减两类。在原子性的实现自增自减少的过程中通过unsafe. getAndAddLong()方法进行值的设置。

unsafe.getAndAddLong()方法的内部首先是获取旧的value并且通过compareAndSwapLong()方法保证在旧值v不变的基础上才能改为新值v+delta。

public final long getAndAddLong(Object o, long offset, long delta) {
    long v;
    do {
        v = getLongVolatile(o, offset);
    } while (!compareAndSwapLong(o, offset, v, v + delta));
    return v;
}

public final long get() {
    return value;
}

public final long getAndSet(long newValue) {
    return unsafe.getAndSetLong(this, valueOffset, newValue);
}

public final long getAndIncrement() {
    return unsafe.getAndAddLong(this, valueOffset, 1L);
}

public final long getAndDecrement() {
    return unsafe.getAndAddLong(this, valueOffset, -1L);
}

public final long getAndAdd(long delta) {
    return unsafe.getAndAddLong(this, valueOffset, delta);
}

public final long getAndUpdate(LongUnaryOperator updateFunction) {
    long prev, next;
    do {
        prev = get();
        next = updateFunction.applyAsLong(prev);
    } while (!compareAndSet(prev, next));
    return prev;
}

public final long getAndAccumulate(long x, LongBinaryOperator accumulatorFunction) {
    long prev, next;
    do {
        prev = get();
        next = accumulatorFunction.applyAsLong(prev, x);
    } while (!compareAndSet(prev, next));
    return prev;
}

AtomicLong类的set动作包括直接返回值和返回自增自减后的值两类。原子性实现自增自减是借助unsafe.getAndAddLong()方法实现的。

unsafe.getAndAddLong()方法的内部首先是获取旧的value并且通过compareAndSwapLong()方法保证在旧值v不变的基础上才能改为新值v+delta。

 针对incrementAndGet()的实现细节,有一点比较有意思,unsafe.getAndAddLong(this, valueOffset, 1L) + 1L,因为unsafe.getAndAddLong返回的是旧值然后通过+delta实现最终的值。而此时对应value的值通过getAndAddLong()修改成了新值,也就说其实incrementAndGet()方法取的值并不是value的内存地址中对应的值。

public final long incrementAndGet() {
    return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}

public final long decrementAndGet() {
    return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
}

public final long addAndGet(long delta) {
    return unsafe.getAndAddLong(this, valueOffset, delta) + delta;
}

public final long updateAndGet(LongUnaryOperator updateFunction) {
    long prev, next;
    do {
        prev = get();
        next = updateFunction.applyAsLong(prev);
    } while (!compareAndSet(prev, next));
    return next;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值