Vavr Set 字段应该是 volatile、atomic 还是以其他方式声明?

Vavr Set field should be volatile, atomic or declared other way?

在 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。请参阅我的 类似问题。 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,以便在以原子方式存储结果之前调用它。确保您使用的是没有副作用的纯函数,因为更新函数可能会被调用多次,以防引用同时被另一个线程自动更新。