Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存和释放内存。Java中的Unsafe类为我们提供了类似C++手动管理内存的能力。Unsafe类是"final"的,不允许继承。
xxxValue()方法:将 Number 对象转换为xxx数据类型的值并返回。
Unsafe.getUnsafe();获取unsafe对象;
public native long objectFieldOffset(Field var1);方法用于获取某个字段相对Java对象的“起始地址”的偏移量
AtomicInteger.class.getDeclaredField("value")是拿到atomicInteger的value字段的field对象
valueoffset是拿到value的相对于AtomicInteger对象的地址偏移量valueOffset
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;
public AtomicInteger(int initialValue) { value = initialValue; } public AtomicInteger() { } public final int get() { return value; } public final void set(int newValue) { value = newValue; }
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; }
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源码结构上几乎相同,不再说明
对比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; }