在ConcurrentHashMap中修改值的首选方法是什么?

obe*_*ger 5 java concurrency thread-safety concurrenthashmap

假设我有一个高读,低写并且需要存储应用程序数据的并发映射:

ConcurrentMap<UUID, Data> map = new ConcurrentHashMap<UUID, Data>();
Run Code Online (Sandbox Code Playgroud)

然后,在启动期间和通过用户输入,数据将添加到地图中:

public void createData(Data newData) {
    map.put(newId, newData); // etc...
}
Run Code Online (Sandbox Code Playgroud)

如果我需要更改数据,我应该:

A)使Data类对象不可变,然后每次需要对Data对象进行更改时执行put操作:

public void changeData(UUID oldId, Foo newInfo) {
    Data oldData = map.get(oldId);
    Data newData = new Data(oldData, newInfo); // Constructor for demo only
    map.put(newData);
    saveToDatabase(newData);
}
Run Code Online (Sandbox Code Playgroud)

B)使用volatile字段,原子引用或最终并发字段使Data类对象可变但是线程安全,并根据需要简单地修改对象:

public void changeData(UUID oldId, Foo newInfo) {
    Data data = map.get(id);
    data.changeSomething(newInfo);
    saveToDatabase(data);
}
Run Code Online (Sandbox Code Playgroud)

C)以上都不是

mik*_*łak 7

A)是更好的选择,原因有两个:

  1. 因为在您的场景中,读取更频繁,所以应该减少它们的开销.volatile在这种情况下,添加其他同步(例如)对您不利.
  2. 通过使用带有额外自定义保护措施(可能有错误)的可变对象,您几乎无法通过使用来改变您的生活ConcurrentHashMap.