在多线程并发请求中,我们假设有这样的一些情景:
if(a){
xxxxx;
a = false;
yyyyy;
}
这里存在线程安全的问题:多个线程可能都读到a的值进入了代码块,然后都去修改了a的值;其实只需要一个线程执行就可以了,也就是:如何保证只初始化一次,不会重复初始化?
答案:使用AtomicBoolean类
AtomicBoolean
位于Java.util.concurrent.atomic包,这个包里面提供了一组原子类。
基本特性:当有多个线程同时执行这些类的实例包含的方法时,具有排他性。即当某个线程进入方法,以原子方式执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,这只是一种逻辑上的理解。实际上是借助硬件的相关指令来实现的,不会阻塞线程(或者说只是在硬件级别上阻塞了)。
API
1、public final boolean compareAndSet(boolean expect, boolean update);
把当前对象值与expect相比较
1)如果相等,把对象值设置为update,并返回为true(设置成功)
2)如果不等,直接返回false(设置失败)
2、public final void set(boolean newValue);
无条件地设置为给定值
3、public final boolean getAndSet(boolean newValue);
获取并返回旧的值(当前值),同时,重新设置新的值。
常见用法:
示例1:
public class InitXxxService{
private AtomicBoolean initState = new AtomicBoolean(false); // 注意:系统默认值也是false
@Override
public void init() {
if (! initState.compareAndSet(false, true)) {//init once
return ;
}
//TODO 写初始化代码
}
}
示例2:
AtomicBoolean started = new AtomicBoolean(false);
if (started.compareAndSet(false, true)) {
call.enqueue(object : Callback<R> {
@override
onResponse(call: Call<R>, response: Response<R>) {
}
@override
onFailure(call: Call<R>, throwable: Throwable) {
}
});
}