Java CHM同步

时间:2017-01-13 01:25:23

标签: java multithreading concurrenthashmap

关注这个问题(Java thread safety - multiple atomic operations?),我不想添加更多问题,但现在我有疑问:

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中是否有任何方法可以原子地完成这项工作?

2 个答案:

答案 0 :(得分:2)

在您的具体情况下,您可能希望使用ConcurrentHashMap的{​​{3}}:

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

来自javadocs:

  

如果存在指定键的值,则尝试在给定键及其当前映射值的情况下计算新映射。 整个方法调用以原子方式执行

所以不需要显式同步。

答案 1 :(得分:1)

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

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

只关注此问题,唯一可能的问题是有人在"A"检查后删除if处找到的设置。 如果您没有删除地图条目,则根本不需要同步。

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

您也可以

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

由于您实际上并没有生产新的Set,我觉得这比computeIfPresent(它应该计算一个新值)更具惯用性。

请注意,您还需要使所有这些Set都是线程安全的。