volatile上的原子变量

tjrkku2a  于 2021-08-20  发布在  Java
关注(0)|答案(3)|浏览(301)

由于原子变量是易变的,所以即使您只需要易变性方面,也始终使用原子变量有什么缺点吗?

crcmnpdw

crcmnpdw1#

变量不能是原子的。原子性和挥发性之间有着明显的区别。
原子性:如果在给定时间只有一个线程可以执行一组指令,则该操作称为原子性。
易变:易变的特性确保了可见性。如果一个线程修改了一些易失性状态,其他线程将获得最新的更新状态。
示例:

volatile boolean flag; 

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

如果多个线程正在处理FlipOffFlag操作,则即使标志是可变的,标志的值也将不确定。这就是FlipOffflag操作需要原子化的原因。我们可以通过添加关键字“synchronized”使FlipOffFlag操作原子化。

zc0qhyus

zc0qhyus2#

当创建最终的原子对象后,不同的线程使用该对象来更改内部状态时,一切都像是不稳定的。
但是,周围还有一个额外的对象示例。消耗内存和速度性能。在这种情况下,它应该是常量/有效的final,并且它的创建应该在其他线程访问之前完成。
另一个方面——我实际上不记得从java参考中读到过,但在别处读到过——是有几个字段,当一个字段是 volatile 修改后,其他线程的其他字段也将更新。
原子常量(或1项的类似常量数组)仍然具有可变状态,有时会被滥用以使用 Stream 只能访问常量的操作。这意味着 Atomic 并不意味着使用多线程。
在里面 x = x + c; ( volatile x )你会读到最新的 x ,但在加入 c 另一个线程可能会改变 x 你仍然会给x赋值一个过时的和。这里需要原子性。或 if (x > 0) x = c; .
所以要回答这个问题:根据脆弱的环境,它们在某种程度上是可以互换的。我明白你为什么喜欢原子,但有一些简单的例子 volatile 性能要高得多,特别是在细粒度并发中。
最后一句话:我不是完全有信心,不管我在这里是否完全正确。

o8x7eapl

o8x7eapl3#

从并发性的Angular 来看,以下各项之间没有区别:

final AtomicInteger foo1 = new AtomicInteger();

volatile int foo2;

foo1.get/set与读写foo2相同。两者都将提供原子性、可见性和订购保证。如果查看例如atomicinteger的代码,您将看到一个volatile int变量。
原子的主要使用情形是很容易执行读修改写操作,例如递增计数器。您可以访问更轻松的排序形式,如getrelease和setacquire。但是您可以使用atomicfieldreference和varhandles做同样的事情(尽管语法不那么漂亮)。
原子的一个缺点是额外的内存使用和间接寻址。

相关问题