Java中的java.util.concurrent.atomic
包提供了一系列的原子操作类,这些类可以在多线程环境中安全地操作单个变量而无需使用锁。这些类通过硬件级别的原子操作(如CAS,Compare-And-Swap)来确保线程安全,性能通常比锁机制更高。
常见的原子操作类
-
AtomicBoolean
- 表示一个
boolean
值,可以原子地读写。 - 常用方法:
get()
: 获取当前值。set(boolean newValue)
: 设置新的值。compareAndSet(boolean expect, boolean update)
: 如果当前值等于期望值expect
,则将其设置为update
。
- 表示一个
-
AtomicInteger
- 表示一个
int
值,可以原子地进行加减、设置和比较操作。 - 常用方法:
get()
: 获取当前值。set(int newValue)
: 设置新的值。getAndIncrement()
: 获取当前值并递增。incrementAndGet()
: 递增并获取新值。compareAndSet(int expect, int update)
: 如果当前值等于期望值expect
,则将其设置为update
。
- 表示一个
-
AtomicLong
- 和
AtomicInteger
类似,但表示一个long
值。 - 常用方法:
get()
: 获取当前值。set(long newValue)
: 设置新的值。getAndIncrement()
: 获取当前值并递增。incrementAndGet()
: 递增并获取新值。compareAndSet(long expect, long update)
: 如果当前值等于期望值expect
,则将其设置为update
。
- 和
-
AtomicReference<T>
- 表示一个对象引用,可以原子地读写。
- 常用方法:
get()
: 获取当前引用。set(T newValue)
: 设置新的引用。compareAndSet(T expect, T update)
: 如果当前引用等于期望引用expect
,则将其设置为update
。
-
AtomicStampedReference<V>
- 类似于
AtomicReference
,但还带有一个整数“标记”,可以用于解决ABA问题(即在一次比较中,值从A变成B再变回A,导致CAS操作误认为值未改变)。 - 常用方法:
getReference()
: 获取当前引用。getStamp()
: 获取当前标记。set(V newReference, int newStamp)
: 设置新的引用和标记。compareAndSet(V expectReference, V newReference, int expectStamp, int newStamp)
: 如果当前引用和标记都等于期望值,则将其设置为新的引用和标记。
- 类似于
-
AtomicIntegerArray
- 表示一个
int
数组,可以对数组中的每个元素进行原子操作。 - 常用方法:
get(int i)
: 获取索引i
处的元素值。set(int i, int newValue)
: 设置索引i
处的元素值。getAndIncrement(int i)
: 获取索引i
处的元素值并递增。compareAndSet(int i, int expect, int update)
: 如果索引i
处的元素值等于期望值expect
,则将其设置为update
。
- 表示一个
-
AtomicLongArray
- 和
AtomicIntegerArray
类似,但表示一个long
数组。 - 常用方法:
get(int i)
: 获取索引i
处的元素值。set(int i, long newValue)
: 设置索引i
处的元素值。getAndIncrement(int i)
: 获取索引i
处的元素值并递增。compareAndSet(int i, long expect, long update)
: 如果索引i
处的元素值等于期望值expect
,则将其设置为update
。
- 和
-
AtomicReferenceArray<E>
- 表示一个对象引用数组,可以对数组中的每个元素进行原子操作。
- 常用方法:
get(int i)
: 获取索引i
处的引用。set(int i, E newValue)
: 设置索引i
处的引用。compareAndSet(int i, E expect, E update)
: 如果索引i
处的引用等于期望引用expect
,则将其设置为update
。
应用场景
- 计数器:如网站访问量统计,可以使用
AtomicInteger
或AtomicLong
。 - 标志位:如线程的启动和停止标志,可以使用
AtomicBoolean
。 - 对象引用:如更新某个共享对象的引用,可以使用
AtomicReference
。 - 解决ABA问题:如需要精确控制对象的版本,可以使用
AtomicStampedReference
。 - 数组元素的原子操作:如需要对数组中的元素进行原子操作,可以使用
AtomicIntegerArray
、AtomicLongArray
或AtomicReferenceArray
。