我理解AtomicInteger和其他原子变量允许并发访问。在什么情况下通常使用这个类?
当前回答
如果您查看AtomicInteger具有的方法,您将注意到它们倾向于对应于对int的常见操作。例如:
static AtomicInteger i;
// Later, in a thread
int current = i.incrementAndGet();
是线程安全的版本:
static int i;
// Later, in a thread
int current = ++i;
方法映射如下: ++i是i. incrementandget () i++就是i. getandincrement () ——i是i. decrementandget () i——是i. getanddecrement () I = x = I .set(x) X = I = X = I .get()
还有其他方便的方法,如compareAndSet或addAndGet
其他回答
就像gabuzo说的,当我想通过引用传递一个整型时,有时我使用AtomicIntegers。它是一个内置类,具有特定于体系结构的代码,因此它比我可以快速编写的任何MutableInteger更容易,也可能更优化。也就是说,这感觉像是对课程的滥用。
Atomic classes are not general purpose replacements for java.lang.Integer and related classes. They do not define methods such as equals, hashCode and compareTo. (Because atomic variables are expected to be mutated, they are poor choices for hash table keys.) Additionally, classes are provided only for those types that are commonly useful in intended applications. For example, there is no atomic class for representing byte. In those infrequent cases where you would like to do so, you can use an AtomicInteger to hold byte values, and cast appropriately. You can also hold floats using Float.floatToRawIntBits(float) and Float.intBitsToFloat(int) conversions, and doubles using Double.doubleToRawLongBits(double) and Double.longBitsToDouble(long) conversions.
参考:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html
AtomicInteger的主要用途是在多线程上下文中,并且需要在不使用synchronized的情况下对整数执行线程安全操作。基本类型int上的赋值和检索已经是原子的,但AtomicInteger附带的许多操作在int上不是原子的。
最简单的是getAndXXX或xXXAndGet。例如,getAndIncrement()是i++的原子等价物,它不是原子的,因为它实际上是三个操作的捷径:检索、加法和赋值。compareAndSet对于实现信号量、锁、锁存器等非常有用。
使用AtomicInteger比使用同步执行相同的操作更快,可读性更强。
一个简单的测试:
public synchronized int incrementNotAtomic() {
return notAtomic++;
}
public void performTestNotAtomic() {
final long start = System.currentTimeMillis();
for (int i = 0 ; i < NUM ; i++) {
incrementNotAtomic();
}
System.out.println("Not atomic: "+(System.currentTimeMillis() - start));
}
public void performTestAtomic() {
final long start = System.currentTimeMillis();
for (int i = 0 ; i < NUM ; i++) {
atomic.getAndIncrement();
}
System.out.println("Atomic: "+(System.currentTimeMillis() - start));
}
在我使用Java 1.6的PC上,原子测试在3秒内运行,而同步测试在5.5秒内运行。这里的问题是同步操作(notatomic++)非常短。所以同步的成本相对于操作来说是非常重要的。
除了原子性,AtomicInteger还可以作为一个可变版本的Integer,例如在map中作为值使用。
AtomicInteger有两个主要用途:
As an atomic counter (incrementAndGet(), etc) that can be used by many threads concurrently As a primitive that supports compare-and-swap instruction (compareAndSet()) to implement non-blocking algorithms. Here is an example of non-blocking random number generator from Brian Göetz's 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; } } } ... } As you can see, it basically works almost the same way as incrementAndGet(), but performs arbitrary calculation (calculateNext()) instead of increment (and processes the result before return).
在Java 8中,原子类扩展了两个有趣的函数:
int getAndUpdate(IntUnaryOperator updateFunction) int updateAndGet(IntUnaryOperator updateFunction)
两者都使用updateFunction来执行原子值的更新。区别在于第一个返回旧值,第二个返回新值。updateFunction可以实现为执行比标准操作更复杂的“比较和设置”操作。例如,它可以检查原子计数器不低于零,通常它需要同步,这里的代码是无锁的:
public class Counter {
private final AtomicInteger number;
public Counter(int number) {
this.number = new AtomicInteger(number);
}
/** @return true if still can decrease */
public boolean dec() {
// updateAndGet(fn) executed atomically:
return number.updateAndGet(n -> (n > 0) ? n - 1 : n) > 0;
}
}
代码取自Java原子示例。
推荐文章
- Java 8流和数组操作
- Java Regex捕获组
- Openssl不被视为内部或外部命令
- 如何添加自定义方法到Spring Data JPA
- 如何在Ubuntu中设置Java环境路径
- 无法执行dex:在Eclipse中超过GC开销限制
- 有人能解释一下JPA和Hibernate中的mappedBy吗?
- 是什么导致JNI调用变慢?
- Java中的&和&&有什么区别?
- 使用Java的Collections.singletonList()?
- Maven使用多个src目录编译
- 导入时无法解析符号
- 用谓词限制流
- 为特定的代码行禁用特定的Checkstyle规则?
- Java中生成UUID字符串的有效方法(UUID. randomuuid ().toString()不带破折号)