具有不可变值的java ConcurrentHashMap同步替换?
我在多线程程序中使用ConcurrentHashMap。映射将serverid映射到包含有关服务器的更多信息的对象(无论服务器是否联机,最近使用了多少等)。ServerID和ServerInformation都是不可变的
为了更新服务器信息,我正在或多或少地执行此问题中建议的B)点: What is the preferred way to modify a value in ConcurrentHashMap?
即(修改为使用我自己的变量名)如下:
public void addUsage(ServerID id, long moreUsage) {
ServerInfo oldInfo = serverMap.get(id);
ServerInfo newInfo = oldInfo.addUsage(moreUsage);
serverMap.put(id, newInfo);
}
现在我的问题是:是否应该同步此方法以排除丢失更新的可能性
还是有其他方法可以实现这一点?可能类似于以下内容(根据我的原始版本进行编辑,以删除一个明显的错误):
public void addUsage(ServerID id, long moreUsage) {
ServerInfo oldInfo = serverMap.get(id);
ServerInfo newInfo = oldInfo.addUsage(moreUsage);
while (!serverMap.replace(id, oldInfo, newInfo) ) {
oldInfo = serverMap.get(id);
newInfo = oldInfo.addUsage(moreUsage);
// try again later
Thread.sleep(SOME_TIME);
};
}
# 1 楼答案
是的,替换方法是解决这个问题的正确方法。只需记住在您的值对象上适当地覆盖相等
(这假设计算newValue相对便宜,冲突相对较少。如果这是一个密集的计算,并且冲突很常见,那么引入互斥并序列化计算可能是值得的。)
最好是将作业重新提交到为线程提供服务的任何队列,或者将其放入延迟队列,而不是实际将工作线程置于睡眠状态。休眠工作线程总体上是令人伤心的,并且缺乏可伸缩性