从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内存
*屏障,因为value使用的是volatile修饰
*/
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);
}
附上Unsafe的功能:
- 操作内存,包括分配内存与释放内存
- 获取内存地地址,修改对象属性值,哪怕是私有属性
- 挂起与恢复线程,LockSupport.part()底层就是Unsafe.park()
- CAS操作
参考文章:
高性能SPSC无锁队列设计之路
set与lazySet区别
lazySet & set
sun.misc.Unsafe类详解
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。