什么时候使用volatile原语(例如boolean,integer或long)代替AtomicBoolean,AtomicInteger或AtomicLong反之亦然?
ass*_*ias 17
可见性语义完全相同,使用原子基元很有用的情况是当你需要使用它们的原子方法时.
例如:
if (volatileBoolean) {
volatileBoolean = !volatileBoolean;
}
Run Code Online (Sandbox Code Playgroud)
可能会在多线程环境中创建问题,因为变量可能会在两行之间发生变化.如果您需要测试和分配是原子的,您可以使用:
atomicBoolean.compareAndSet(true, false);
Run Code Online (Sandbox Code Playgroud)
Pet*_*rey 16
如果要设置或获取值,则使用普通volatile可以更简单,更高效.(但不能得到&设定值)
如果您需要更多操作,如getAndIncrement或compareAndSwap,则需要使用AtomicXxxx类.
这些Atomic*类包装了volatile相同类型的基元.从来源:
public class AtomicLong extends Number implements java.io.Serializable {
...
private volatile long value;
...
public final long get() {
return value;
}
...
public final void set(long newValue) {
value = newValue;
}
Run Code Online (Sandbox Code Playgroud)
所以.
何时使用volatile原语(例如boolean,integer或long)而不是AtomicBoolean,AtomicInteger或AtomicLong
如果您正在做的就是获取并设置一个,Atomic*那么您可能只需要一个volatile字段.
......反之亦然?
什么Atomic*课给你不过是提供更先进的功能,如方法incrementAndGet(),compareAndSet()其他人实现多个操作(Get /递增/集,测试/套),并没有锁.这就是为什么Atomic*课程如此强大.
同样重要的是要注意,volatile使用Atomic*类包装字段是从对象角度封装关键共享资源的好方法.这意味着开发人员不能只处理该字段,假设它没有共享,可能会field++;引入引入竞争条件的其他代码的问题.
我们已经开始禁止volatile在我们的源代码中使用它,因为编写并不总是按预期工作的代码非常容易.
根据我的经验,人们添加volatile来在线程之间共享一个值.然后,其他人开始修改该值.大多数时候,这都有效.但在生产中,你开始出现奇怪的错误,这些错误很难追查.计数器增加100'000次(测试只增加10次)但最终为99'997.在Java 1.4中,长值可能真的很少被破坏.
该Atomic*助手类,而另一方面,征收只是一个小的开销,并为标榜他们总是工作.
因此,除非你有一个很好的理由(*),否则volatile总是更喜欢Atomic*辅助类.
如果你不确切知道Atomic*帮助器类中每个字符的作用,那么你应该真的避免volatile.
*:过早优化绝不是一个好理由.
| 归档时间: |
|
| 查看次数: |
6196 次 |
| 最近记录: |