![](/img/trans.png)
[英]Java concurrency using ConcurrentHashMap with synchronized block
[英]Concurrency issue when using ConcurrentHashMap
我一直在研究REST API作為一些技能的一部分。 在將對象插入ConcurrentHashMap時,我當前的實現有一個小的並發問題。
我的代碼檢查消耗的JSON是否包含ID。 如果不是,我創建一個新的唯一ID並插入該對象。 如果是,我繼續檢查我的地圖中是否已存在該ID。 如果不存在具有該ID的對象,則插入該對象。
檢查HashMap是否包含匹配的ID並插入對象之間的時間段在許多並發POST請求發生時證明是一個問題。 如果在gcdMap.get(obj.getId()) == null
和gcdMap.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.