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()
是线程安全的,例如。 G。返回最终属性,并且不会在并行线程中执行任何删除操作,您的代码也是线程安全的,因为 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();
}
对结果调用 getNum()
是可能的,因为与 putIfAbsent()
相比,如果插入之前值不存在,则返回 null,它返回刚刚计算的结果值。
关于java - 在 ConcurrentHashMap 上进行的操作是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35909582/