AtomicBoolean
这个类是Automic包下的类,用于提供对应类型的原子操作
源码解析
这个类提供了一个可以原子更新的Boolean值。有关原子变量属性的描述,请参照java.util.concurrent.atomic包规范。AtomicBoolean可以用于作为原子更新的标志,但是不能作为java.lang.Boolean的替代使用。
这个类自JDK1.5开始提供
这个类实现了java.io.Serializable接口,关于java.io.Serializable接口详见对应的介绍
这里value变量使用了volatile修饰,关于volatile修饰放到关键字对应的内容下,简单说一下,熟悉这个关键词底层实现的人知道,这个关键词最终是加了内存屏障。主要体现在三点
1.保证写volatile变量会强制把CPU写缓存区的数据刷新到内存
2.读volatile变量时,使缓存失效,强制从内存中读取最新的值
3.由于内存屏障的存在,volatile变量还能阻止重排序
//序列化ID
private static final long serialVersionUID = 4654671469794556979L;
// 获取Unsafe实例用于进行Unsafe的相关操作,详见Unsafe介绍
private static final Unsafe unsafe = Unsafe.getUnsafe();
//用于存储通过Unsafe获取的元素偏移量
private static final long valueOffset;
//用于存储元素的变量(整形)
private volatile int value;
//静态化块用于初始化valueOffset
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicBoolean.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
接下来是用于初始化的构造方法
//利用给定的初始化元素(布尔型)初始化一个新的AtomicBoolean
public AtomicBoolean(boolean initialValue) {
value = initialValue ? 1 : 0;
}
//无参构造函数,即将value按照默认的0初始化,也即是说初始化为false
public AtomicBoolean() {
}
接下来是一个用于获取value的方法
public final boolean get() {
//返回value元素所代表的布尔值,除0以外都是true
return value != 0;
}
再往下是原子操作
关于compareAndSet和weakCompareAndSet补充一个专题配合Volatile关键字一起写一个
//如果当前的value元素和expect所期望的数据相同,利用给定的update原子化(CAS操作)更新value
//返回true标示更新成功,返回false标示期望值和实际值不相同
public final boolean compareAndSet(boolean expect, boolean update) {
int e = expect ? 1 : 0;
int u = update ? 1 : 0;
//this用于传递第一个参数,作为当前对象(对于CAS操作来说就是目标所在的对象),
//然后是valueOffset是目标属性偏移量
//e是CAS操作的期望值
//u是更新值
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}
//这个方法在1.8之前都是和上面的那个一毛一样滴,但是这个方法作为一个接口职责,
//对上层调用不能保证调用的失败的时候是真正的失败,换句话说有可能是虚假的失败
//但是一般来说这个方法所提供的效率要高于上一个
//1.9中这个方法仍然是和上一个一样的,但是在jdk1.9中开始出现了一个@HotSpotIntrinsicCandidate注解
//这个注解表达了虽然你看到的源码是一样的,但是不排除虚拟机对这个进行优化的可能性
public boolean weakCompareAndSet(boolean expect, boolean update) {
int e = expect ? 1 : 0;
int u = update ? 1 : 0;
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}
设置value的方法
//这个方法无条件的将元素设定为给定的值
public final void set(boolean newValue) {
value = newValue ? 1 : 0;
}
这个方法只能保证最终会设置为给定的值,不能保证存储对其他线程的立即可见,也就是说这个更改是有延迟的。这个方法通常只有在底层字段是volatile修饰的时候才能生效。value是在Volatile修饰下的
public final void lazySet(boolean newValue) {
int v = newValue ? 1 : 0;
unsafe.putOrderedInt(this, valueOffset, v);
}
原子的更新元素,然后把之前的值返回回去
public final boolean getAndSet(boolean newValue) {
boolean prev;
//自旋锁,每次CAS失败后都会重新读取
do {
prev = get();
} while (!compareAndSet(prev, newValue));
return prev;
}
把元素按照String返回
public String toString() {
return Boolean.toString(get());
}
网友评论