簡體   English   中英

使用ConcurrentHashMap時的並發問題

[英]Concurrency issue when using ConcurrentHashMap

我一直在研究REST API作為一些技能的一部分。 在將對象插入ConcurrentHashMap時,我當前的實現有一個小的並發問題。

我的代碼檢查消耗的JSON是否包含ID。 如果不是,我創建一個新的唯一ID並插入該對象。 如果是,我繼續檢查我的地圖中是否已存在該ID。 如果不存在具有該ID的對象,則插入該對象。

檢查HashMap是否包含匹配的ID並插入對象之間的時間段在許多並發POST請求發生時證明是一個問題。 如果在gcdMap.get(obj.getId()) == nullgcdMap.put(obj.getId(), obj); gcdMap.get(obj.getId()) == null之間執行第一個請求,那么具有生成ID的請求可能會被指定ID的請求寫入。 gcdMap.put(obj.getId(), obj); 第二個請求的代碼行。 我一直在使用Thread.Sleep()來重現這個問題。

public static ConcurrentMap<Long, GCDObject> gcdMap = new ConcurrentHashMap<Long, GCDObject>();
@POST

@Consumes(MediaType.APPLICATION_JSON)
public GCDObject create(GCDObject obj) throws GCDRequestException {
    obj.setTimestamp(LocalDateTime.now());
    obj.setResult(GCD.calculate(obj.getX(), obj.getY()));

    if (obj.getId() != null) { // JSON contains ID
        if (gcdMap.get(obj.getId()) == null) { // If map does not contain obj with ID already,
            Thread.sleep(1000);
            gcdMap.put(obj.getId(), obj); // Put obj into map.
            return obj;
        } else { // else map already contains ID,
            throw new GCDRequestException();
        }
    } else { // JSON contains no ID
        obj.setId(buildId()); // Build ID
        gcdMap.put(obj.getId(), obj); // Put into map
        return obj;
    }
}

我已經看到了使用鎖的建議,但是無法以解決此問題的方式實現它們。 任何可能幫助我制定解決方案的示例,文檔或文章都將不勝感激。

編輯:我在下面的評論中大約拼錯了三次。 我現在無法編輯它們但我注意到了!

使用putIfAbsent()有條件地插入:

if (gcdMap.putIfAbsent(obj.getId(), obj) == null) { // If map did not contain obj with ID already,
    return obj;
} else { // else map already contained ID,
    throw new GCDRequestException();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM