简体   繁体   English

使用ConcurrentHashMap时的并发问题

[英]Concurrency issue when using ConcurrentHashMap

I've been working on a REST API as part of some up skilling. 我一直在研究REST API作为一些技能的一部分。 My current implementation has a small concurrency issue when inserting objects into my ConcurrentHashMap. 在将对象插入ConcurrentHashMap时,我当前的实现有一个小的并发问题。

My code checks to see whether the consumed JSON contains an ID. 我的代码检查消耗的JSON是否包含ID。 If no, I create a new unique ID and insert the object. 如果不是,我创建一个新的唯一ID并插入该对象。 If yes I continue on to check if the ID already exists in my map. 如果是,我继续检查我的地图中是否已存在该ID。 If no object with the ID exists then I insert the object. 如果不存在具有该ID的对象,则插入该对象。

The period between checking if the HashMap contains a matching ID and inserting the object is proving to be a problem when many concurrent POST requests are being made. 检查HashMap是否包含匹配的ID并插入对象之间的时间段在许多并发POST请求发生时证明是一个问题。 A request that has a generated ID can be potentially written over by a request where the ID has been specified if the first request is executed between gcdMap.get(obj.getId()) == null and gcdMap.put(obj.getId(), obj); 如果在gcdMap.get(obj.getId()) == nullgcdMap.put(obj.getId(), obj); gcdMap.get(obj.getId()) == null之间执行第一个请求,那么具有生成ID的请求可能会被指定ID的请求写入。 gcdMap.put(obj.getId(), obj); lines of code of the second request. 第二个请求的代码行。 I have been using Thread.Sleep() to reproduce this problem. 我一直在使用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;
    }
}

I have seen suggestions for the use of locks but have not been able to implement them in a way that solves this issue. 我已经看到了使用锁的建议,但是无法以解决此问题的方式实现它们。 Any examples, documentation or articles that might help me work out a solution would be greatly appreciated. 任何可能帮助我制定解决方案的示例,文档或文章都将不胜感激。

Edit: I've misspelled absent about three times in the comments below. 编辑:我在下面的评论中大约拼错了三次。 I can't edit them now but I noticed! 我现在无法编辑它们但我注意到了!

Use putIfAbsent() to insert conditionally: 使用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