繁体   English   中英

在ConcurrentHashMap上进行此操作是否线程安全?

[英]Is it Thread-safe on this operating on 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吗? 还是有更好的方法来实现?

如果VoteItem#getNum()是线程安全的,例如返回final属性, 并且没有在并行线程中执行删除操作,则您的代码也是线程安全的,因为putIfAbsent()没有机会覆盖现有条目,因此没有机会让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()get()之间执行并发删除从而导致NPE,在这种情况下不会发生这种情况。

并考虑使用computeIfAbsent()代替putIfAbsent() ,以避免不必要的VoteItem创建:

public void vote(float graduation) {
    datum.computeIfAbsent(graduation, g -> new VoteItem(g, new AtomicInteger(0)))
         .getNum()
         .incrementAndGet();
}

可以在result上调用getNum() ,因为与putIfAbsent() ,如果在插入之前不存在值的情况下返回null,则它仅返回计算值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM