使用volatile原语而不是primefaces变量有什么区别?
可能重复:
Java:volatile boolean vs AtomicBoolean
什么时候使用volatile
原语(例如boolean
, integer
或long
)而不是AtomicBoolean
, AtomicInteger
或AtomicLong
,反之亦然?
可见性语义完全相同,使用primefaces基元很有用的情况是当你需要使用它们的primefaces方法时。
例如:
if (volatileBoolean) { volatileBoolean = !volatileBoolean; }
可能会在multithreading环境中创建问题,因为变量可能会在两行之间发生变化。 如果您需要测试和分配是primefaces的,您可以使用:
atomicBoolean.compareAndSet(true, false);
如果要设置或获取值,则使用普通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; }
所以。
何时使用volatile原语(例如boolean,integer或long)而不是AtomicBoolean,AtomicInteger或AtomicLong
如果您正在做的就是获取并设置Atomic*
那么您可能只需要使用volatile
字段。
……反之亦然?
然而, Atomic*
类为您提供的方法是提供更高级function的方法,例如incrementAndGet()
, compareAndSet()
以及其他实现多个操作(get / increment / set,test / set) 而无需锁定的方法。 这就是Atomic*
类如此强大的原因。
同样重要的是要注意,使用Atomic*
类包装volatile
字段是从对象角度封装关键共享资源的好方法。 这意味着开发人员不能只处理该字段,假设它没有共享可能注入field++;
问题field++;
或引入竞争条件的其他代码。
我们已经开始禁止在我们的源代码中使用volatile
,因为编写代码并不总是按预期工作。
根据我的经验,人们添加volatile来在线程之间共享一个值。 然后,其他人开始修改该值。 而且大多数时候,这都有效。 但在生产中,你开始出现奇怪的错误,这些错误很难追查。 计数器增加100’000次(测试只增加10次)但最终为99’997。 在Java 1.4中,长值可能真的很少被破坏。
另一方面, Atomic*
帮助程序类只需要很小的开销,它们总是像宣传的那样工作。
因此,除非你有一个非常好的理由(*)使用volatile
,否则总是更喜欢Atomic*
辅助类。
如果你不确切知道Atomic*
helper类中的每个字符是什么,那么你应该真的避免volatile
。
*:过早优化绝不是一个好理由。