关注这个问题(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中是否有任何方法可以原子地完成这项工作?
答案 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都是线程安全的。