有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

具有不可变值的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) 个答案

  1. # 1 楼答案

    是的,替换方法是解决这个问题的正确方法。只需记住在您的值对象上适当地覆盖相等

    (这假设计算newValue相对便宜,冲突相对较少。如果这是一个密集的计算,并且冲突很常见,那么引入互斥并序列化计算可能是值得的。)

    最好是将作业重新提交到为线程提供服务的任何队列,或者将其放入延迟队列,而不是实际将工作线程置于睡眠状态。休眠工作线程总体上是令人伤心的,并且缺乏可伸缩性