package java.util.concurrent.atomic;
import sun.misc.Unsafe;
/**
* 可以原子化的更新int值。
* AtomicInteger可以用作程序中的计数器,但是不能作为Integer的替代品。
* 尽管如此,AtomicInteger继承自Number,这允许它能统一的访问处理数字化类的tools和utilities。
*
*/
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// 使用Unsafe.compareAndSwapInt用于更新操作
// 原子类都使用到了sun.misc.Unsafe,这个类的构造方法是私有的,另外,受Java Secutiry的限制,这个类只能被JDK信任的类实例化
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 内存中,value相对于this的地址偏移量,通过this的内存地址和这个偏移量可以获得value的内存地址
private static final long valueOffset;
static {
try {
//获取value字段的偏移量
valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 以volatile定义value,保证其可见性
private volatile int value;
/**
* 以给定的初始值创建一个新的AtomicInteger
*
* @param initialValue 初始值
*/
public AtomicInteger(int initialValue) {
value = initialValue;
}
/**
* 以0作为初始值创建AtomicInteger
*/
public AtomicInteger() {
}
/**
* 获取当前值
* value被volatile关键字修饰,所以线程每次都会重新读取这个值,而不是使用 本地副本
*
* @return 当前值
*/
public final int get() {
return value;
}
/**
* 设置成给定的值
* volatile提供了和synchronized相同的可见性,但是仅此而已,它只保证每次都能读到最新值
* 当两个线程都读取了value的同一个值,然后做修改时,有一次update操作会被覆盖掉,这是因为读和写不是一个原子操作
* 要使 volatile变量提供理想的线程安全,必须同时满足下面两个条件:
* 1.对变量的写操作不依赖于当前值。
* 2.该变量没有包含在具有其他变量的不变式中
*
* 这里set正是基于第一条
*
* @param newValue 新值
*/
public final void set(int newValue) {
value = newValue;
}
/**
* 最终设置成给定的值
*
* @param newValue 新值
* @since 1.6
*/
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
/**
* 设置给定的值,并返回老值,这是一个原子操作
*
* @param newValue 新值
* @return 老值
*/
public final int getAndSet(int newValue) {
for (;;) {
int current = get();
if (compareAndSet(current, newValue))
return current;
}
}
/**
* 原子化更新给定的值,在当前值和期望值相同时
* Compare And Swap->比较并交换
* CAS操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。
* 如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。
*
* @param expect 期望值
* @param update 新值
* @return true 如果成功就返回true。返回false说明当前值和期望值不同
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
/**
* 原子化更新给定的值,在当前值和期望值相同时
*
* 更新也许会不合逻辑的失败,不提供保证,在极少的情况下用于替代compareAndSet
*
* @param expect 期待值
* @param update 新值
* @return true 如果成功返回true
*/
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
/**
* 原子递增并返回递增之前的值
*
* @return 递增之前的值
*/
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
/**
* 原子递减并返回递减之前的值
*
* @return 递减之前的值
*/
public final int getAndDecrement() {
for (;;) {
int current = get();
int next = current - 1;
if (compareAndSet(current, next))
return current;
}
}
/**
* 原子相加并返回相加之前的值
*
* @param delta 要加的值
* @return 相加之前的值
*/
public final int getAndAdd(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return current;
}
}
/**
* 原子递增并返回递增后的值
* i++这种操作看起来是一次操作,实际上可以分成读取i,加一,写回i这三步,所以它不是一个原子操作
*
* @return 递增后的值
*/
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
/**
* 原子递减并返回递减后的值
* i--这种操作看起来是一次操作,实际上可以分成读取i,减一,写回i这三步,所以它不是一个原子操作
*
* @return 递减后的值
*/
public final int decrementAndGet() {
for (;;) {
int current = get();
int next = current - 1;
if (compareAndSet(current, next))
return next;
}
}
/**
* 原子操作式地将加上给定的值
*
* @param delta 要加的值
* @return 加完得到的结果
*/
public final int addAndGet(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return next;
}
}
/**
* 返回当前值的字符串形式
* @return 当前值的字符串形式
*/
public String toString() {
return Integer.toString(get());
}
public int intValue() {
return get();
}
public long longValue() {
return (long)get();
}
public float floatValue() {
return (float)get();
}
public double doubleValue() {
return (double)get();
}
}
相关参考:
源码剖析之sun.misc.Unsafe
sun.misc.unsafe类的使用
JAVA CAS原理深度分析