AtomicBoolean简介
AtomicBoolean类位于java.util.concurrent.atomic包下的原子变量,AtomicBoolean是Java中的一个原子类,用于表示一个布尔类型的值。
AtomicBoolean作用
AtomicBoolean主要的作用就是:提供对布尔类型变量的原子操作,这样可以避免并发访问时的竞态条件和数据不一致的问题。
AtomicBoolean使用场景
如果需要对某个boolean类型的变量进行原子操作,可以考虑使用AtomicBoolean,它主要有以下应用场景:
1.控制某个操作的执行
AtomicBoolean可以用来控制某个操作的执行,比如在一个多线程环境下,只允许一个线程执行某个操作。
可以将AtomicBoolean对象初始化为false,然后在需要执行该操作的线程中使用compareAndSet()方法将其设置为true。
2.作为一种开关
AtomicBoolean还可以作为一种开关,用于控制某个功能的开启和关闭。
比如:在一个多线程环境下,可以使用AtomicBoolean对象表示某个功能的开启状态,如果AtomicBoolean对象的值为true,则表示该功能已经开启,否则表示该功能已经关闭。
3.替代volatile boolean
AtomicBoolean可以替代volatile boolean,因为它可以提供与volatile相同的可见性和线程安全性,同时还提供了compareAndSet()方法,可以实现原子操作。
AtomicBoolean方法使用
1.AtomicBoolean构造函数
AtomicBoolean它有两个构造方法,如下所示:
public AtomicBoolean(boolean initialValue) { value = initialValue ? 1 : 0; } public AtomicBoolean() { }
第二个构造方法AtomicBoolean(boolean initialValue),可以指定初始值。
2.AtomicBoolean获取值
采用get()方法,如下所示:
AtomicBoolean atomicBoolean = new AtomicBoolean(); boolean value = atomicBoolean.get(); System.out.println(value);
get():返回AtomicBoolean对象的当前值。
3.AtomicBoolean设置值
可以使用 set() 方法对值进行重新设置,如下所示:
atomicBoolean.set(true);
set(boolean newValue):将AtomicBoolean对象的值设置为newValue。
4.compareAndSet进行原子更新
可以使用compareAndSet进行原子更新,如下所示:
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); }
如果AtomicBoolean对象的当前值等于expect,则将其设置为update,并返回true,否则返回false。
5.核心操作 getAndSet
以原子方式设置为给定值并返回前一个值,底层实现如下:
public final boolean getAndSet(boolean newValue) { boolean prev; do { prev = get(); } while (!compareAndSet(prev, newValue)); return prev; }
getAndSet(boolean newValue):将AtomicBoolean对象的值设置为newValue,并返回原来的值。
AtomicBoolean实现原理
AtomicBoolean的实现原理是基于CAS(Compare and Swap)算法。
CAS是一种无锁算法,它通过比较对象的当前值和预期值是否相等来实现原子操作。
如下图所示:
如上图显示,两个线程:线程1和线程2同时修改值,如果通过CAS来实现,具体流程如下:
- 在内存地址V当中,存储着值为7的变量
- 线程1想要把变量的值增加1,对线程1来说,旧的预期值A=7,要修改的新值B=8
- 线程2抢先一步,把内存值V修改:8
- 线程1开始提交更新,首先对比了预期值A=7和实际值V的比较8(Compare),发现A不等于V的实际值,提交失败
在多线程环境下,多个线程可以同时尝试执行CAS操作,但只有一个线程能够成功执行操作,其他线程则需要重试。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》