I do not understand why FindBug complains about this code
Foo obj = map.get(id);
if(obj == null) {
obj = new Foo();
map.put(id, obj);
}
obj.add(someObject);
Second Version
Foo tmp = new Foo();
obj = map.putIfAbsent(id, tmp);
if (obj == null)
obj = tmp
obj.add(someObject);
If I do second version, I have to create Foo
object every time.
Foo obj = map.get(id);
if(obj == null) {
lock.writeLock().lock();
try {
obj = new Foo();
map.put(id, obj);
}finally {
lock.writeLock().unlock();
}
}
obj.add(someObject);
With third version, FindBugs still complains about not atomic.
It says :
Sequence of calls to concurrenthashmap may not be atomic
Changing put to putIfAbsent
, FindBugs still complains.
Findbugs observes that the pair of method invocations map.get(id)
, map.put(id, obj)
may not be atomic, meaning that it is possible that some other thread modifies map
in between.
For example, another thread may record a different mapping for key id
between those two calls, which then gets silently lost when the first thread executes its map.put()
. Since you bother to test whether there is initially a mapping for that key, this result seems unlikely to be an acceptable one.
One way to approach this issue would be to use ConcurrentHashMap.putIfAbsent()
in place of both calls (not just in place of put()
).
If some other thread adds an entry with that key while your thread is evaluating the if ()
statement, your thread will overwrite it.
You need to use putIfAbsent
only , not not interact with the map otherwise.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.