AtomicInteger 的实际用途
2022-08-31 05:26:28
我有点理解AtomicInteger和其他原子变量允许并发访问。但是,在什么情况下通常使用此类?
我有点理解AtomicInteger和其他原子变量允许并发访问。但是,在什么情况下通常使用此类?
有两个主要用途:AtomicInteger
作为原子计数器(等),可由多个线程同时使用incrementAndGet()
作为支持比较和交换指令 () 的基元来实现非阻塞算法。compareAndSet()
以下是Brian Göetz的Java Concurrency In Practice中的非阻塞随机数生成器的示例:
public class AtomicPseudoRandom extends PseudoRandom {
private AtomicInteger seed;
AtomicPseudoRandom(int seed) {
this.seed = new AtomicInteger(seed);
}
public int nextInt(int n) {
while (true) {
int s = seed.get();
int nextSeed = calculateNext(s);
if (seed.compareAndSet(s, nextSeed)) {
int remainder = s % n;
return remainder > 0 ? remainder : remainder + n;
}
}
}
...
}
如您所见,它的工作方式基本上与 相同,但执行任意计算()而不是增量(并在返回之前处理结果)。incrementAndGet()
calculateNext()
我能想到的绝对最简单的例子是使递增成为原子操作。
使用标准 ints:
private volatile int counter;
public int getNextUniqueIndex() {
return counter++; // Not atomic, multiple threads could get the same result
}
使用 AtomicInteger:
private AtomicInteger counter;
public int getNextUniqueIndex() {
return counter.getAndIncrement();
}
后者是执行简单突变效应(特别是计数或唯一索引)的非常简单的方法,而无需诉诸于同步所有访问。
更复杂的无同步逻辑可以用作一种乐观锁定 - 获取当前值,基于此计算结果,设置此结果iff值仍然是用于执行计算的输入,否则重新开始 - 但是计数示例非常有用,如果有任何涉及多个线程的提示,我将经常用于计数和VM范围的唯一生成器, 因为它们非常容易使用,我几乎认为使用普通.compareAndSet()
AtomicIntegers
ints
虽然您几乎总是可以使用适当的声明实现相同的同步保证,但其美妙之处在于线程安全内置于实际对象本身中,而不需要担心碰巧访问该值的每种方法的可能交错和监视器。在调用时意外违反线程安全比返回并记住(或不)事先获取正确的监视器集要困难得多。ints
synchronized
AtomicInteger
int
getAndIncrement()
i++