簡體   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