在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;
}
}
我应该使用挥发物吗?我应该改用AtomicRef<Set<String>>
吗?
答案 0 :(得分:1)
我会使用AtomicReference
。请参阅我的answer来回答类似的问题。波动性绝对是不够的,因为它仅保证对变量的更新将立即对其他线程可见(它有效地禁用了对其的缓存访问)。不过,并发线程访问将不会同步,因此可能发生两个线程同时构建更新的Set
,并且其中一个线程将覆盖另一个线程更改的情况。
给出两个同时运行的线程T1和T2,想象以下事件序列:
以上序列的最终值为V×U2,因此实际上丢失了更新U1。
另一方面, AtomicReference
保证该变量是原子更新的。您必须将updater函数传递给AtomicReference
,因此将在原子存储结果之前对其进行调用。确保您使用的是没有副作用的纯函数,因为如果同时另一个线程以原子方式对引用进行了更新,则可能会多次调用updater函数。