Atomic
374字约1分钟
2024-08-08
Java
的 java.util.concurrent
包除了提供底层锁、并发集合外,还提供了一组原子操作的封装类,它们位于 java.util.concurrent.atomic
包
我们以 AtomicInteger
为例,它提供的主要操作有
增加值并返回新值:
int addAndGet(int delta)
加1后返回新值:
int incrementAndGet()
获取当前值:
int get()
用
CAS
方式设置:int compareAndSet(int expect, int update)
Atomic
类是通过无锁(lock-free
)的方式实现的线程安全(thread-safe
)访问。它的主要原理是利用了 CAS
:Compare and Set
如果我们自己通过 CAS
编写 incrementAndGet()
,它大概长这样:
public int incrementAndGet(AtomicInteger var) {
int prev, next;
do {
prev = var.get();
next = prev + 1;
} while ( ! var.compareAndSet(prev, next));
return next;
}
CAS
是指,在这个操作中,如果 AtomicInteger
的当前值是 prev
,那么就更新为 next
,返回 true
。如果 AtomicInteger
的当前值不是 prev
,就什么也不干,返回 false
。通过 CAS
操作并配合 do ... while
循环,即使其他线程修改了 AtomicInteger
的值,最终的结果也是正确的
我们利用 AtomicLong
可以编写一个多线程安全的全局唯一 ID
生成器
class IdGenerator {
AtomicLong var = new AtomicLong(0);
public long getNextId() {
return var.incrementAndGet();
}
}
通常情况下,我们并不需要直接用 do ... while
循环调用 compareAndSet
实现复杂的并发操作,而是用 incrementAndGet()
这样的封装好的方法,因此,使用起来非常简单
在高度竞争的情况下,还可以使用 Java 8
提供的 LongAdder
和 LongAccumulator