繁体   English   中英

Volatile 上的原子变量

[英]Atomic variables over Volatile

由于原子变量是易变的,即使您只需要易变性方面,始终使用原子变量是否有任何缺点?

变量不能是原子的。 原子性和易失性之间有明显的区别。

原子性:如果在给定时间只有一个线程可以执行一组指令,则该操作称为原子性。

易变:易变的性质确保了可见性。 如果一个线程修改了一些易失性状态,其他线程将获得最近更新的状态。

例子 :

volatile boolean flag; 


public void flipTheFlag(){
  if(flag == true){
      flag = false;
  }else{
      flag = true;
  }
}

如果多个线程正在执行flipTheFlag 操作,即使flag 是volatile 变量,flag 的值也会不确定。 这就是为什么操作 flipTheFlag 需要是原子的。 我们可以通过添加关键字“同步”来使 flipTheFlag 操作原子化。

  1. 当创建最终的Atomic对象后,不同的线程使用该对象来更改内部状态时,一切都像volatile 一样

    然而,周围有一个额外的对象实例。 消耗内存和速度性能。 在这种情况下,它应该是常量/有效最终的,并且它的创建应该其他线程可以访问之前完成。

  2. 另一个方面 - 我实际上不记得从 java 参考中读取的正确性,但在其他地方读过 - 是有几个字段,当一个字段在修改时volatile时,其他字段也将针对其他线程更新。

  3. 原子常量(或类似的 1 项常量数组)仍然具有可变状态,有时会被滥用以使用只能访问常量的Stream操作来收集聚合结果。 这意味着Atomic并不意味着多线程使用。

  4. x = x + c; ( volatile x ) 您将读取最新的x ,但是在添加c ,另一个线程可能会更改x并且您仍然会为 x 分配一个陈旧的总和。 这里需要原子性。 或者if (x > 0) x = c; .

所以要回答这个问题:根据脆弱的上下文,它们在某种程度上是可以互换的。 我可以理解您为什么更喜欢 Atomic,但在一些简单的情况下, volatile性能要高得多,尤其是在细粒度并发中。

最后一句话:我不是完全有信心,我在这里是否完全正确。

从并发的角度来看,以下之间没有区别:

final AtomicInteger foo1 = new AtomicInteger();

volatile int foo2;

foo1.get/set 与 foo2 的读取和写入相同。 两者都将提供原子性、可见性和排序保证。 如果您查看例如 AtomicInteger 的代码,您将看到一个 volatile int 变量。

Atomic 的主要用例是很容易进行读修改写操作,例如增加计数器。 并且您可以访问更轻松的排序形式,例如 getRelease 和 setAcquire。 但是你可以使用 AtomicFieldReference 和 VarHandles 做同样的事情(虽然语法不太漂亮)。

atomic 的一个缺点是额外的内存使用和间接性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM