当前位置: 技术文章>> Java 中的 AtomicLong 和 LongAdder 有什么区别?

文章标题:Java 中的 AtomicLong 和 LongAdder 有什么区别?
  • 文章分类: 后端
  • 9615 阅读

在Java并发编程中,AtomicLongLongAdder 是两种常用的用于执行原子操作的类,它们都能在多线程环境下安全地更新长整型(long)的值。尽管它们的目标相似,但它们在实现方式、性能特点以及适用场景上存在一些显著差异。下面,我们将深入探讨这两个类的区别,并尝试以高级程序员的视角来阐述这些差异。

1. 基本概念与用途

AtomicLong

AtomicLong 是 Java 并发包(java.util.concurrent.atomic)中的一个类,它提供了在单个变量上执行原子操作的能力。原子操作意味着这些操作在执行过程中不会被线程调度机制中断,从而保证了操作的完整性和可见性。AtomicLong 主要用于实现计数器、累加器等场景,在这些场景中,多个线程需要安全地更新同一个长整型变量的值。

LongAdder

LongAdder 是 Java 8 引入的一个新类,同样位于 java.util.concurrent.atomic 包中。它旨在提供比 AtomicLong 更高的并发级别下的吞吐量。LongAdder 通过将单个 long 值的更新分散到多个变量上(通常是一个基数值和多个单元格),从而减少了在高并发情况下对单一热点变量的竞争,进而提高了性能。

2. 实现机制

AtomicLong

AtomicLong 的实现依赖于底层的 CAS(Compare-And-Swap)操作。CAS 是一种乐观锁技术,它尝试更新一个值时,会先检查该值是否等于预期值,如果等于则更新为新值,并返回成功;如果不等,则说明该值已被其他线程修改,此时操作失败,并通常会重试直到成功。这种机制虽然能有效保证操作的原子性,但在高并发场景下,由于大量线程竞争同一资源,可能会导致较高的重试成本,从而影响性能。

LongAdder

LongAdder 的设计则更加巧妙。它内部维护了一个基数值(base)和多个单元格(cells),每个线程在更新时,会首先尝试更新其关联的单元格(如果尚未初始化,则先初始化),如果检测到足够的竞争(例如,通过检测到某个单元格的冲突次数过高),则会尝试更新基数值。最终,LongAdder 的值是所有单元格和基数值的总和。这种设计减少了线程间的竞争,因为每个线程通常只更新自己的单元格,从而提高了在高并发场景下的性能。

3. 性能差异

由于实现机制的不同,LongAdderAtomicLong 在性能上表现出明显的差异。在大多数高并发场景下,LongAdder 的性能要优于 AtomicLong。这是因为 LongAdder 通过减少线程间的竞争,降低了 CAS 操作失败的概率,从而减少了重试的次数和上下文切换的开销。然而,在并发级别较低时,AtomicLong 的性能可能与 LongAdder 相当,甚至在某些情况下可能更优,因为 LongAdder 的额外逻辑(如单元格的初始化和维护)可能会引入一定的开销。

4. 适用场景

AtomicLong

  • 适用于并发级别不是特别高,且对内存占用有严格要求的场景。
  • 当需要保证操作的绝对原子性,且不介意在极端高并发下性能有所下降时。

LongAdder

  • 适用于高并发场景,特别是当多个线程频繁更新同一个长整型变量时。
  • 当性能是首要考虑因素,且可以接受一定的内存开销时。

5. 注意事项

  • 尽管 LongAdder 在高并发下性能更优,但它提供的不是严格意义上的原子操作。如果应用场景需要确保每次更新操作的原子性(即,不希望更新过程中被其他线程打断),则 AtomicLong 是更好的选择。
  • LongAdder 提供了 sum() 方法来获取当前的总值,但需要注意的是,这个方法并不保证返回的是一个“实时”的值,因为在多线程环境下,值是在不断变化的。如果需要非常精确的值,可能需要考虑其他同步或协调机制。
  • 在使用 LongAdder 时,应注意其内存占用可能会随着并发级别的增加而增加,因为需要为更多的线程分配单元格。

6. 实战应用与码小课

在实际的软件开发中,选择 AtomicLong 还是 LongAdder 取决于具体的应用场景和性能要求。如果你正在开发一个高并发的系统,且性能是关键考量因素,那么 LongAdder 很可能是一个更好的选择。同时,理解这两个类的内部实现和工作原理,对于编写高效、可维护的并发代码至关重要。

作为一名高级程序员,不断学习和掌握新的并发编程工具和技术是非常重要的。码小课(这里自然融入你的网站名)作为一个专注于技术分享的平台,提供了丰富的并发编程、Java 核心技术等课程内容,可以帮助你不断提升自己的技术水平和实战能力。通过深入学习 AtomicLongLongAdder 的使用场景和性能特点,你将能够更加灵活地应对各种并发编程挑战,编写出更加高效、健壮的代码。

推荐文章