JavaCHM同步

Java CHM synchronisation

跟进这个问题(),我不想再补充问题了,但现在我有这个疑问:

private final Map<String, Set<String>> data = Maps.newConcurrentMap();

... then in a method ...

if (data.containsKey("A")) {
    data.get("A").add("B");
}

应该是这样的:

synchronized(data) {
    if (data.containsKey("A")) {
        data.get("A").add("B");
    }
}

为了线程安全。对吗?

所以操作是原子的,但是组合它们需要同步,对吗?到那时,只使用一个简单的 HashMap 而不是并发 HashMap 是否有意义,因为我们正在手动处理同步?

CHM 中是否有任何方法可以自动完成这项工作?

在您的具体情况下,您可能希望使用 computeIfPresent method of ConcurrentHashMap:

data.computeIfPresent("A", (k, v) -> { v.add("B"); return v; } );

来自 javadocs:

If the value for the specified key is present, attempts to compute a new mapping given the key and its current mapped value. The entire method invocation is performed atomically.

所以不需要显式同步。

synchronised(data) {
    if (data.containsKey("A")) {
        data.get("A").add("B");
    }
}

您可能需要显示更多代码。

仅此来看,唯一可能的问题是有人在您的 if 检查后删除了在 "A" 找到的集合。 如果您从不删除映射条目,则根本不需要同步。

如果您同时删除地图条目,您可以使用 computeIfPresent 获得更新的地图。

你也可以

Set<String> set = data.get("A");
if (set != null) set.add("B");

由于您实际上并没有生成新的 Set,我发现这比 computeIfPresent(应该计算一个新值)更符合习惯。

请注意,您还需要制作所有这些套装 thread-safe。