AtomicBoolean源码学习

从AtomicBoolean源码上的注释看,AtomicBoolean用于应用中需要原子地更新flags,不过它不能够代替Boolean的使用,不能代替主要是从性能上考虑的吧。
一、先来看一下AtomicBoolean里的属性

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

unsafe与valueOffset都是类级别的属性。unsafe是Unsafe对象的引用,后面方法里的原子操作都依赖它;valueOffset是AtomicBoolean对象地址偏移量,是unsafe对象方法里的不可或缺的参数之一。

static{
    try{
        valueOffset = unsafe.objectFieldOffset(
            AtomicBoolean.class.getDeclaredField("value"));
    }catch(Exception e){
        throw new Error(ex);
    }
}
private volatile int value;//修改后对其它线程立即可见

上面静态块在获取属性 'value' 的内存地址偏移量,这个偏移量对于给定的field是唯一的,并且每次调用返回都是一样。
二、接着说几个重要的方法
两个构造器:

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

一个有参,一个无参,无参时成员变量value值为0,也就是false.
再来看下面一组方法:

/**
 *Atomically sets the value to the given updated value if
 *the current value == the expected value.
 *此方法最终由底层硬件缓存锁实现原子性,不可中断。偏移量所在的值
 *与传入的expect相等且修改成update则返回true,如果比较不相等则
 *返回false。这个方法不会自旋。
*/
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);
}
/**
*Atomically sets to the given value and returns the *previous value.
*设置新的旧并返回旧值,不成功会一直重试,compareAndSet则不会
*/
public final boolean getAndSet(boolean newValue){
    boolean prev;
    do{
        prev = get();
    }while(!(compareAndSet(prev,newValue));
    return prev;
}

再来一组方法:

/**
*Unconditionally sets to the given value
*无条件设置给定的值
*在修改value值时,会在其前后分别加StoreStore/StoreLoad内存
*屏障
*/
public final void set(boolean newValue){
    value = newValue ? 1 : 0;
}
/**
*Eventually sets to the given value
*最终设置给定的值,从字面上理解可以看出一定延迟,不过确实也是
*lazySet可以让一个线程在没有其它线程volatile写或者synchronized
*动作发生前,本地缓存的写可以不必马上刷回主存,
*有可能是几纳秒后被其它线程可见,但性能据说要比set快3倍。
*使用lazySet修改value时只会在其前加StoreStore屏障,
*这正是*lazySet比set效率高的原因,正是这个特性使得lazySet很适合
*于SPSC的数据结构的实现
*SPSC:单product单consumer
*/
public fianl void lazySet(boolean newValue){
    int v = newValue ? 1 : 0;
    unsafe.putOrderedInt(this,valueOffset,v);
}

参考文章:
高性能SPSC无锁队列设计之路
set与lazySet区别
lazySet & set
sun.misc.Unsafe类详解

你可能感兴趣的:(java,源码学习)