在ConcurrentHashMap上运行它是否是线程安全的?

时间:2016-03-10 06:54:52

标签: java concurrency concurrenthashmap

private final ConcurrentHashMap<Float, VoteItem> datum = new ConcurrentHashMap<>();

public void vote(float graduation) {
    datum.putIfAbsent(graduation, new VoteItem(graduation, new AtomicInteger(0)));
    datum.get(graduation).getNum().incrementAndGet();
}

方法投票是否完全是线程安全的? VoteItem.getNum()返回一个AtomicInteger?或者,如果有更好的方法来实现它?

1 个答案:

答案 0 :(得分:4)

如果VoteItem#getNum()是线程安全的,e。 G。返回最终属性,在并行线程中不执行任何删除,您的代码也是线程安全的,因为putIfAbsent()没有机会覆盖现有条目,因此{{}}没有机会1}}返回被覆盖的条目。

但是有更常见的方法可以使用get()的结果来实现它,如果给定键存在,则会返回现有值:

putIfAbsent()

这也可以处理并发删除的可能性。与您的代码相反,可以在public void vote(float graduation) { VoteItem i = datum.putIfAbsent(graduation, new VoteItem(graduation, new AtomicInteger(1))); if (i != null) i.getNum().incrementAndGet(); } putIfAbsent()之间执行并发删除,从而导致NPE,这里不会出现这种情况。

并考虑使用computeIfAbsent()代替get()以避免无理由putIfAbsent()创作:

VoteItem

可以在结果上调用public void vote(float graduation) { datum.computeIfAbsent(graduation, g -> new VoteItem(g, new AtomicInteger(0))) .getNum() .incrementAndGet(); } ,因为与getNum()相反,如果在插入之前值不存在则返回null,它只返回计算值。