AtomicInteger:先看看源码
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
//成员属性value得内存地址相对于对象内存地址得偏移量
private static final long valueOffset;
static {
try {
//通过objectFieldOffset()获取value变量在内存中得偏移
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
//volatile 修饰value,保证数据得可见性
private volatile int value;
/**
* Creates a new AtomicInteger with the given initial value.
*
* @param initialValue the initial value
*/
public AtomicInteger(int initialValue) {
value = initialValue;
}
/**
* Creates a new AtomicInteger with initial value {@code 0}.
*/
public AtomicInteger() {
}
/**
*获取值
*/
public final int get() {
return value;
}
/**
* Atomically sets to the given value and returns the old value.
* 以原子得方式设置给定值,返回旧值
* @param newValue the new value
* @return the previous value
*/
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
unsafe.class:
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
// 通过当前对象和偏移地址 找到实际存储得值
var5 = this.getIntVolatile(var1, var2);
//public final native boolean compareAndSwapInt(Object o, long offset, int expected,int x); //o 为规定对象,offset对象内存得偏移量,通过这个偏移量快速定位并设置或者获取该地段得值,expected 表示当前内存中期望得值,x 表示应该设置得值 // 如果内存中得值 和期待值不一样 就循环 重新去读取,知道读取到最新得值
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
1.什么是偏移地址
偏移地址也称为偏移量,8086/8088 内部ALU只能进行16位得计算,但cpu的地址线是20位,处理的
8086 有20跟地址总线,每一根可以某一时刻传0或1,20位得二进制就是2^20 = 1048576,寻址范围是1M
读取得是20位,但是cpu最大只能处理16位 这咋办?
长度为4 得16 进制用长度为3得16进制表示;
实际地址: 段地址 * 16 + 偏移地址;
* 16 是啥意思? — 向左移动4位
demo:1402:100
1402H * 16 + 0100
即:14020H –基地址 * 16
+ 0100H –偏移地址
= 14120H –实际物理地址
2. volatile 只能保证数据得可见性,不能保证数据得原子性
volatile int value;
一个线程修改value之后会及时将value值返回到内存中,其他线程读取的时候能保证value是最新得值;
但是读取之后value++;这种操作 就不能保证得到得值 是自己想要得结果.
Atomic 使用了cas 来实现原子性;
3. Atomic 不能解决ABA 得问题;
就是一个值由A 边为B,后又被边回A,其他线程在读取的时候并不知道其中得操作过程,只知道一个最终答案;
AtomicStampedReference 保存了一个referance,可以对比是否存在ABA 得问题;