gpt4 book ai didi

java.util.并发 : external synchronize to remove map value

转载 作者:行者123 更新时间:2023-11-29 09:11:46 25 4
gpt4 key购买 nike

我需要根据唯一键跟踪多个值,即 1(a,b) 2(c,d) 等...

该解决方案由多个线程访问,因此我定义了以下内容;

ConcurrentSkipListMap<key, ConcurrentSkipListSet<values>>

我的问题是当value set size为0时key的移除是否需要同步?我知道这两个类是“并发的”并且我查看了 OpenJDK 源代码但是我在一个线程 T1 之间似乎有一个窗口检查 Set 是否为空并删除 remove(...) 中的 Map另一个线程 T2 调用 add(...)。结果是 T1 删除了最后一个 Set 条目并删除了与 T2 交错的 Map 只是添加了一个 Set 条目。因此,Map 和 T2 Set 条目被 T1 删除,数据丢失。

我只是“同步”add() 和 remove() 方法还是有“更好”的方法?

Map被多个线程修改,但只通过两个方法。

代码片段如下;

protected static class EndpointSet extends U4ConcurrentSkipListSet<U4Endpoint> {
private static final long serialVersionUID = 1L;
public EndpointSet() {
super();
}
}

protected static class IDToEndpoint extends U4ConcurrentSkipListMap<String, EndpointSet> {
private static final long serialVersionUID = 1L;
protected Boolean add(String id, U4Endpoint endpoint) {
EndpointSet endpoints = get(id);
if (endpoints == null) {
endpoints = new EndpointSet();
put(id, endpoints);
}
endpoints.add(endpoint);
return true;
}

protected Boolean remove(String id, U4Endpoint endpoint) {
EndpointSet endpoints = get(id);
if (endpoints == null) {
return false;
} else {
endpoints.remove(endpoint);
if (endpoints.size() == 0) {
remove(id);
}
return true;
}
}
}

最佳答案

因为您的代码存在数据竞争。可能发生的情况示例:

  • 可以在 if (endpoints.size() == 0)remove(id); 之间添加一个线程 - 你看到了
  • add 中,一个线程可以读取 EndpointSet endpoints = get(id); 中的非空值,另一个线程可以从该集合中删除数据,删除该集合从 map 上,因为集合是空的。然后,初始线程会向该集合添加一个值,该值不再保留在 map 中 => 数据也会丢失,因为它变得无法访问。

解决问题的最简单方法是使添加和删除同步。但是您随后失去了使用 ConcurrentMap 的所有性能优势。

或者,您可以简单地将空集保留在 map 中 - 除非您有内存限制。您仍然需要某种形式的同步,但它更容易优化。

如果争用(性能)是一个问题,您可以通过同步键或值来尝试更细粒度的锁定策略,但这可能非常棘手(由于字符串池,锁定字符串并不是一个好主意) .

似乎在所有情况下,您都可以使用非并发集,因为您需要自己在外部同步它。

关于java.util.并发 : external synchronize to remove map value,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11967725/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com