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