我有一张队列地图。对映射和队列的访问必须是线程安全的。数据由不同的线程从队列中添加和删除。
我实现了这个结构
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;
}}
发布于 2014-12-02 01:46:59
该代码是不正确的,因为从HashMap读取数据不受任何锁的保护。因此,从映射中读取数据的线程不知道任何其他线程已经更新了数据。
而且效率不高;您的结构不能通过两个线程同时支持enqueue和dequeue,而且使用两个同步块会消耗资源。您也可以同时同步这两种方法。
更有效的实现方式是使用并发数据结构:
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;
}
}发布于 2014-12-02 01:38:05
不是线程安全的:在dequeue中读取散列映射不受锁保护。当并发写入的map处于不一致的内部状态时,您可能最终会尝试读取。
https://stackoverflow.com/questions/27233901
复制相似问题