首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java.util.concurrent:外部同步以移除映射值

java.util.concurrent:外部同步以移除映射值
EN

Stack Overflow用户
提问于 2012-08-15 18:27:07
回答 1查看 146关注 0票数 2

我需要跟踪与唯一键对应的多个值,例如1(a,b) 2(c,d)等。

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

代码语言:javascript
复制
ConcurrentSkipListMap<key, ConcurrentSkipListSet<values>>

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

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

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

代码语言:javascript
复制
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;
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-15 18:49:17

事实上,你的代码有数据竞争。以下是可能发生的情况的示例:

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

解决问题的最简单方法是同时添加和删除synchronized。但是,您将失去使用ConcurrentMap的所有性能优势。

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

如果争用(性能)是一个问题,您可以尝试一种更细粒度的锁定策略,方法是在键或值上进行同步,但这可能相当棘手(由于字符串池的存在,在String上锁定并不是一个好主意)。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11967725

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档