编程语言
首页 > 编程语言> > JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类

JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类

作者:互联网

JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类

Unsafe

Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存和释放内存。Java中的Unsafe类为我们提供了类似C++手动管理内存的能力。Unsafe类是"final"的,不允许继承。

Number类(abstract)

xxxValue()方法:将 Number 对象转换为xxx数据类型的值并返回。

Atomic Boolean-Integer-Long UML图

AtomicInteger源码

获得value字段相对于AtomicInteger对象“起始地址”的偏移量:

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;

static {
    try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
    } catch (Exception ex) { throw new Error(ex); }
}

private volatile int value;

构造函数/get/set

 public AtomicInteger(int initialValue) {
     value = initialValue;
 }

public AtomicInteger() {
}

public final int get() {
        return value;
}

public final void set(int newValue) {
	value = newValue;
}

基于native方法的原子操作

getAnd×××方法,get在前就是先获取值,然后操作,类似于i++;get在后则类似于i--,先操作,然后返回操作后的值。

AtomicInteger 的 getAndIncrement、getAndDecrement、getAndAdd、incrementAndGet、decrementAndGet、addAndGet 都是使用unsafe.getAndAddInt方法直接操作底层内存偏移地址对应的整型数值进行加减操作;getAndAccumulate、accumulateAndGet、updateAndGet方法都是通过输入IntUnaryOperator接口类型的参数来实现逻辑的。

AtomicInteger中方法写法比较类似,以updateAndGet为例说明,其他方法在下面有注释

public final int updateAndGet(IntUnaryOperator updateFunction) {
	int prev, next;
    do {
        prev = get();
        next = updateFunction.applyAsInt(prev);
    } while (!compareAndSet(prev, next));
    return next;
}

set方法跟lazySet的区别

    public final void set(int newValue) {
        value = newValue;
    }
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }

set方法跟lazySet的区别:

​ set方法的设置操作在写操作的前后都加了内存屏障,因为AtomicInteger中的value是volatile修饰的。而lazySet方法并不是直接的操作value字段,而是通过Unsafe类的putOrderedInt方法先通过初始化时候计算出的vlaue字段的偏移变量找到字段地址,然后调用本地方法进行操作的,在本地方法中只在写操作前面加了一个屏障,而后面没有加。

其他方法:

    //cas替换,如果旧值与预期值相同,则swap
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
    //与compareAndSet方法一样,为什么要用这个方法
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
	//原子操作返回当前值,设置新值
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }
	//value++,返回的是原来的值
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
	//value--,返回的是原来的值
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }
	//返回value,然后value+=delta
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }
	//++value,返回的是+1操作之后的value
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }
	//--value
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }
	//value+=delta,然后返回value
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }
	//将给定函数应用于当前值,原子更新结果,返回以前的值。
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }
	//将给定函数应用于当前值,原子更新结果,并返回以前的值
    public final int getAndAccumulate(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return prev;
    }
	//将给定函数应用于当前值和给定值,结果以原子更新当前值,并返回更改后的值
    public final int accumulateAndGet(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return next;
    }

AtomicLong源码与AtomicInteger源码结构上几乎相同,不再说明

AtomicBoolean

与AtomicInteger相同的部分

对比AtomicInteger,AtomicBoolean内部同样包含一个value(int)属性

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;

static {
    try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicBoolean.class.getDeclaredField("value"));
    } catch (Exception ex) { throw new Error(ex); }
}

private volatile int value;

构造函数

有参构造函数就是把传进来的boolean转化成了int

public AtomicBoolean(boolean initialValue) {
    value = initialValue ? 1 : 0;
}
public AtomicBoolean() {
}

其他原子操作方法

AtomicBoolean的其他方法本质上和AtomicInteger没有什么区别,只是操作之前都要把传进来的boolean类型的参数转化为int。

public final boolean compareAndSet(boolean expect, boolean update) {
    int e = expect ? 1 : 0;
    int u = update ? 1 : 0;
    return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}

public boolean weakCompareAndSet(boolean expect, boolean update) {
    int e = expect ? 1 : 0;
    int u = update ? 1 : 0;
    return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}

public final void set(boolean newValue) {
    value = newValue ? 1 : 0;
}

public final void lazySet(boolean newValue) {
    int v = newValue ? 1 : 0;
    unsafe.putOrderedInt(this, valueOffset, v);
}
public final boolean getAndSet(boolean newValue) {
    boolean prev;
    do {
        prev = get();
    } while (!compareAndSet(prev, newValue));
    return prev;
}

标签:JDK1.8,int,unsafe,AtomicInteger,final,源码,value,prev,public
来源: https://www.cnblogs.com/aslanvon/p/15244236.html