目录
AtomicBoolean提供了一种原子性地读写布尔类型变量的解决方案,通常情况下,该类将被用于原子性地更新状态标识位,比如flag。
1、AtomicBoolean 的基本用法
AtomicBoolean类比较简单,其内部实现原理与AtomicInteger类似
1.1、AtomicBoolean 的创建
AtomicBoolean 也提供了个有参,无参 两个构造方法。
//无参 构造方法默认值为 false
AtomicBoolean flag = new AtomicBoolean();
//有参构造方法,可以指定初始值
AtomicBoolean flag1 = new AtomicBoolean(true);
1.2、AtomicBoolean 值得更新
- compareAndSet(boolean expect, boolean update):对比并且设置boolean最新的值,类似于AtomicInteger的compareAndSet方法,期望值与Atomic Boolean的当前值一致时执行新值的设置动作,若设置成功则返回true,否则直接返回false。
- weakCompareAndSet(boolean expect, boolean update):同上。
- set(boolean newValue):设置AtomicBoolean最新的value值,该新值的更新对其他线程立即可见。
- getAndSet(boolean newValue):返回AtomicBoolean的前一个布尔值,并且设置新的值。
public class AtomicBooleanExample {
public static void main(String[] args) {
AtomicBoolean flag = new AtomicBoolean();
boolean andSet = flag.getAndSet(true);
System.out.println("原始值:" + andSet);
System.out.println("当前值:" + flag.get());
}
}
2、AtomicBoolean 内幕
AtomicBoolean的实现方式比较类似于AtomicInteger类,实际上AtomicBoolean内部的value本身就是一个volatile关键字修饰的int类型的成员属性。
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicBoolean.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 通过 volatile 关键字修饰的 value 值
private volatile int value;
3、为什么需要AtomicBoolean
对于int或者long型变量,需要进行加减操作,所以要加锁;但对于一个boolean类型来说,true或false的赋值和取值操作,加上volatile关键字就够了,为什么还需要AtomicBoolean呢?
我们可能存在如下情况:
boolean flag = false;
if(flag == false){
flag = true;
......
}
也就是要实现compare和set两个操作合在一起的原子性,而这也正是CAS提供的功能。上面的代码,就变成:
if(flag.compareAndSet(false, true)){
// TODO
}
4、如何支持 boolean 类型
在Unsafe类中,只提供了三种类型的CAS操作:int、long、Object(也就是引用类型)。如下所示。
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
AtomicBoolean 类型怎么支持呢?
对于用 int 型来代替的,在入参的时候,将 boolean 类型转换成 int 类型;在返回值的时候,将 int 类型转换成 boolean 类型。如下所示。
// 获取 boolean 值 其实是 比较当前 value 值是否为 0
public final boolean get() {
return value != 0;
}
// 设置 boolean 的值,其实最终转换为了 1 或 0
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);
}