java - Vavr Set 字段应该是 volatile 的、原子性的还是以其他方式声明的?

标签 java atomic volatile vavr

在 vavr 中,您拥有不可变的 io.vavr.collection.Set。 考虑到addName(),使用它的正确方法和惯用方法是什么?和names()可以从不同的线程调用吗?

import io.vavr.collection.Set;
import io.vavr.collection.HashSet;
public class Names{
  public/*private*/ /**volatile*/ Set<String> names = HashSet.empty();
  public void addName(String name){
    names = names.add(name);
  }
  public Set<String> names(){
    return names;
  }
}

我应该使用 volatile 吗?我应该使用 AtomicRef<Set<String>>相反?

最佳答案

我会使用AtomicReference。看我的answer类似的问题。 volatile 肯定是不够的,因为它只能保证对变量的更新立即对其他线程可见(它有效地禁用了对其的缓存访问)。不过,并发线程访问不会同步,因此可能会发生两个线程同时构建更新的Set,并且其中一个线程将覆盖其他线程更改的情况。

给定两个并发运行的线程 T1 和 T2,想象以下事件序列:

  1. T1读取变量,当前状态为V
  2. T2读取变量,当前状态为V
  3. T1计算更新状态V×U1
  4. T2计算更新状态V×U2
  5. T1 将变量更新为 V×U1
  6. T2 将变量更新为 V×U2

上述序列的最终值将是 V×U2,因此更新 U1 实际上会丢失。

另一方面,

AtomicReference 保证变量以原子方式更新。您必须将更新器函数传递给 AtomicReference,因此它将在原子存储结果之前被调用。确保您使用的是没有副作用的纯函数,因为如果同时另一个线程以原子方式更新引用,则更新器函数可能会被多次调用。

关于java - Vavr Set 字段应该是 volatile 的、原子性的还是以其他方式声明的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56223825/

相关文章:

c++ - 如何使用 memset 将 volatile 数组设置为零?

java - 垃圾收集和同步可见性

java - 在 Java 中使用 BitSet 跟踪前导零

java - Symbian S60 电子邮件查看组件

c++ - 比较和交换 : synchronizing via different data sizes

c++ - 我可以同时复制一个 shared_ptr 吗?

java - 意外的值自动舍入

java - 前瞻断言(正则表达式)在 JFlex 中不起作用

python - 如何在 python 中对 stdout 进行原子写入?

java - 为什么内在锁对象不需要特殊处理(static、final、volatile)?