2.4 atomic 包原子类

java.util.concurrent.atomic 包提供了一组用于实现原子操作的类。这些类可以用于在多线程环境中执行线程安全的、不可中断的原子操作。原子操作类提供了一种稳定可靠的方式执行原子类操作,而不是使用锁实现。原子操作类适用于各种并发场景,特别在是高并发场景种,原子操作类性能表现非常突出。

atomic 包下面的功能类,性能测试使用到的只有 4 种:分别是 AtomicBoolean、AtomicInteger、AtomicLong 和 LongAdder。

对于前三种,相信你会有一种眼熟的感觉,都有对应的 Java 基础数据类型,使用方式也很相似,把 Java 操作符换成了方法实现取值和赋值功能。下面逐个介绍几位主角。

1. AtomicBoolean

AtomicBoolean 类常用于多线程环境种对 Boolean 值的操作。使用者可以直接对 AtomicBoolean 对象的值进行修改,而不需要借助锁和 synchronized 关键字。下面是 AtomicBoolean 常用的功能。

AtomicBoolean 在性能测试中,通常用来标记线程状态,控制线程启动和停止;资源初始化、重置的状态标记,减少线程间竞争;还可以用来控制并发,限制同时执行某个操作的线程数。

2. AtomicInteger

AtomicInteger 类常用于对整数值的执行原子操作。使用者可以对 AtomicInteger 对象进行线程安全的加、减操作,同样的不需要锁和 synchronized。下面是 AtomicInteger 常用功能。

3. AtomicLong

AtomicLong 功能跟 AtomicInteger 一样,区别在于 AtomicLong 可以表达的整数类型范围更广。两者所能处理的整数范围预期对应基础数据类型所能表示整数类型范围一样。

4. LongAdder

LongAdder 功能与 AtomicLong、AtomicInteger 一模一样,能处理整数值范围与 AtomicLong 一致。区别在于 LongAdder 在高并发计数场景中,性能表现更好。原因在于 LongAdder 使用了分段锁来降低线程竞争,这个设计思路跟 ConcurrentHashMap 一致。如果你将来遇到类似场景,可以阅读这两个类的源码寻找设计灵感。下面介绍一下 LongAdder 的常用功能。

LongAdder 使用场景跟前两者基本重合,如果你需要进行高并发计数、大规模数据聚合操作,优先考虑 LongAdder 实现该功能。

对于高并发并没有一个严格的规范,笔者提供一个数据仅供参考:在 500 线程并发场景下:LongAdder 优势比较明显;在 200 ~ 300 并发场景中,LongAdder 略有优势;在更低的并发中,两者性能无明显差异。

如果在工作中,你仍然无法决断,后面会讲到 Java 微基准测试工具 JMH,可以帮助你在实际场景中做出明智的选择。

书的名字:从 Java 开始做性能测试

如果本书内容对你有所帮助,希望各位不吝赞赏,让我可以贴补家用。赞赏两位数可以提前阅读未公开章节。我也会尝试制作本书的视频教程,包括必要的答疑。

FunTester 原创精华

【连载】从 Java 开始性能测试


↙↙↙阅读原文可查看相关链接,并与作者交流