首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这个结构线程安全吗?

这个结构线程安全吗?
EN

Stack Overflow用户
提问于 2014-12-02 01:31:28
回答 2查看 66关注 0票数 1

我有一张队列地图。对映射和队列的访问必须是线程安全的。数据由不同的线程从队列中添加和删除。

我实现了这个结构

代码语言:javascript
复制
public class Structure {

private final Map<String, LinkedList<String>> queues = new HashMap<>();

public void enqueue(String id, String data) {
    LinkedList<String> queue;
    synchronized (queues) {
        queue = queues.get(id);
        if (queue == null) {
            queue = new LinkedList<>();
            queues.put(id, queue);
        }
    }
    synchronized (queue) {
        queue.add(data);
    }
}

public List<String> dequeue(String id) {
    LinkedList<String> queue;
    synchronized (queues) {
        queue = queues.get(id);
    }
    if (queue != null) {
        synchronized (queue) {
            List<String> q = new LinkedList<>(queue);
            queue.clear();
            return q;
        }
    }
    return null;
}

}

EN

回答 2

Stack Overflow用户

发布于 2014-12-02 01:46:59

该代码是不正确的,因为从HashMap读取数据不受任何锁的保护。因此,从映射中读取数据的线程不知道任何其他线程已经更新了数据。

而且效率不高;您的结构不能通过两个线程同时支持enqueuedequeue,而且使用两个同步块会消耗资源。您也可以同时同步这两种方法。

更有效的实现方式是使用并发数据结构:

代码语言:javascript
复制
public class Structure<K, V> {
    private final Queue<V> EMPTY_QUEUE = new ConcurrentLinkedQueue<>();
    private final Map<K, Queue<V>> queues = new ConcurrentHashMap<>();

    public void enqueue(K id, V data) {
        Queue<V> queue = queues.computeIfAbsent(id, i -> new ConcurrentLinkedQueue<>());
        queue.add(data);
    }

    public List<V> dequeue(K id) {
        Queue<V> queue = queues.getOrDefault(id, EMPTY_QUEUE);
        List<V> resp = new LinkedList<>(queue);
        queue.clear();
        return resp;
    }
}
票数 5
EN

Stack Overflow用户

发布于 2014-12-02 01:38:05

不是线程安全的:在dequeue中读取散列映射不受锁保护。当并发写入的map处于不一致的内部状态时,您可能最终会尝试读取。

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

https://stackoverflow.com/questions/27233901

复制
相关文章

相似问题

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