我理解AtomicInteger和其他原子变量允许并发访问。在什么情况下通常使用这个类?
当前回答
在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中,原子类扩展了两个有趣的函数:
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原子示例。
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).
就像gabuzo说的,当我想通过引用传递一个整型时,有时我使用AtomicIntegers。它是一个内置类,具有特定于体系结构的代码,因此它比我可以快速编写的任何MutableInteger更容易,也可能更优化。也就是说,这感觉像是对课程的滥用。
可以在原子整数或长值上使用compareAndSwap (CAS)实现非阻塞锁。“Tl2”软件事务内存论文这样描述:
我们将一个特殊版本的写锁与每个事务关联起来 内存位置。在其最简单的形式中,版本化写锁是 使用CAS操作获取锁和的单字自旋锁 一个发布它的商店。因为我们只需要一个比特来表示 如果锁已被占用,则使用锁字的其余部分来保存 版本号。
What it is describing is first read the atomic integer. Split this up into an ignored lock-bit and the version number. Attempt to CAS write it as the lock-bit cleared with the current version number to the lock-bit set and the next version number. Loop until you succeed and your are the thread which owns the lock. Unlock by setting the current version number with the lock-bit cleared. The paper describes using the version numbers in the locks to coordinate that threads have a consistent set of reads when they write.
本文介绍了处理器对比较和交换操作的硬件支持,这使得比较和交换操作非常高效。它还声称:
使用原子变量的非阻塞基于cas的计数器有更好的性能 在低到中等争用情况下,性能优于基于锁的计数器
关键是它们允许安全的并发访问和修改。它们通常在多线程环境中用作计数器——在引入它们之前,这必须是一个用户编写的类,将各种方法包装在同步块中。
推荐文章
- 指定的子节点已经有一个父节点。你必须先在子对象的父对象上调用removeView() (Android)
- 对于一个布尔字段,它的getter/setter的命名约定是什么?
- 如何获得当前屏幕方向?
- 如何在Android中渲染PDF文件
- 如何计算一个元素在列表中出现的次数
- c++中类似于java的instanceof
- 我如何解决错误“minCompileSdk(31)指定在一个依赖的AAR元数据”在本机Java或Kotlin?
- 如何POST表单数据与Spring RestTemplate?
- Mockito中检测到未完成的存根
- 我应该如何复制字符串在Java?
- “while(true)”循环有那么糟糕吗?
- 这个方法签名中的省略号(…)是干什么用的?
- Java:如何测试调用System.exit()的方法?
- 带有返回类型的Java方法在没有返回语句的情况下编译
- Java“此语言级别不支持lambda表达式”