ConcurrentHashMap支持的队列的线程安全性

时间:2017-11-08 11:35:31

标签: java multithreading

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DedupingQueue<E> implements QueueWrapper<E> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DedupingQueue.class);

private final Map<E, Future<E>> itemsBeingWorkedOn = new ConcurrentHashMap<>();
private final AsyncWorker<E> asyncWorker; //contains async method backed by a thread pool

public DedupingQueue(AsyncWorker<E> asyncWorker) {
    this.asyncWorker = asyncWorker;
}

@Override
public Future<E> submit(E e) {
    if (!itemsBeingWorkedOn.containsKey(e)) {
        itemsBeingWorkedOn.put(e, asyncWorker.executeWorkAsync(e, this));
    } else {
        LOGGER.debug("Rejected [{}] as it's already being worked on", e);
    }
    return itemsBeingWorkedOn.get(e);
}

@Override
public void complete(E e) {
    LOGGER.debug("Completed [{}]", e);
    itemsBeingWorkedOn.remove(e);
}

@Override
public void rejectAndRetry(E e) {
    itemsBeingWorkedOn.putIfAbsent(e, asyncWorker.executeWorkAsync(e, this));
}

}

我在推理上述代码的线程安全性方面遇到了一些困难。

我认为completerejectAndretry完全是线程安全的,因为地图是线程安全的。但是submit呢,假设AsyncWorker本身不是线程安全的?另外,如何在不使用synchronized (使用内置ConcurrentHashMap保证)的情况下以最有效的方式使其线程安全?

2 个答案:

答案 0 :(得分:2)

submit()不是线程安全的,因为你的check-then-act序列不是原子序列。一个线程的特定键的状态可以在检查之后和调用之前由其他线程更改。使用ConcurrentHashMap中的原子方法(很可能是computeIfAbsent())来解决此问题。

if (!itemsBeingWorkedOn.containsKey(e)) {
    itemsBeingWorkedOn.put(e, asyncWorker.executeWorkAsync(e, this));
}

如果AsyncWorker不是线程安全的,那么整个类也不是线程安全的。但如果没有AsyncWorker源代码,很难推理它。

答案 1 :(得分:2)

compute()方法,该函数接受键,当前值或null如果没有当前映射,并返回值以保留在映射中,或者如果{{1返回。

null

请注意,您的队列未订购。如果您需要FIFO或LIFO订单,则应使用更合适的数据结构,例如@Override public Future<E> submit(E e) { return itemsBeingWorkedOn.compute(e, (k, v) -> { if (v == null) { return asyncWorker.executeWorkAsync(k, this); } else { LOGGER.debug("Rejected [{}] as it's already being worked on", k); return v; } }); } LinkedHashMap语句。