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。
跟进这个问题(
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。