I have tried below code in order to have a unique id for each jj.
As far as I know, computeIfAbsent is thread-safe but:
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService =
Executors.newFixedThreadPool(4);
final Map<String, ConcurrentHashMap<String, Short>> threadSafeMap = new ConcurrentHashMap<>();
threadSafeMap.put("0", new ConcurrentHashMap<>());
threadSafeMap.put("1", new ConcurrentHashMap<>());
for (int i = 1; i <= 10; i++) {
final int jj = i;
executorService.submit(() -> {
int key = jj % 2;
final ConcurrentMap<String, Short> idByName = threadSafeMap.get(String.valueOf(key));
return idByName.computeIfAbsent(String.valueOf(jj), x -> (short) idByName.size());
});
}
executorService.shutdown();
executorService.awaitTermination(5, TimeUnit.SECONDS);
System.out.println(threadSafeMap);
}
Actual value: {0={2=0, 4=0, 6=2, 8=3, 10=4}, 1={1=0, 3=0, 5=2, 7=3, 9=4}}
Expected value for example (due to concurrency): {0={2=0, 4=1, 6=2, 8=3, 10=4}, 1={1=1, 3=0, 5=2, 7=3, 9=4}}
The problem is that I have with 2=0 and 4=0, which is wrong values should be unique!
btw using interger instead of short solve the issue! Could you please help?
Your assumption is wrong, as many different threads could be executing the same mapping function concurrently for different keys.
ConcurrentHashMapis thread-safe but permits concurrent updates to the map. Some callers which are accessing similar parts of the underlying mapping tables may block while waiting for another thread to finish.You won't find that
computeIfAbsent(someKey,mapFunc)runs the mapping function for the same key twice, because it is an atomic operation for that key. So second or concurrent caller would see the value of the first call. However anothercomputeIfAbsent(anotherKey,mapFunc)could be running at exactly the same time which is why your mapping function may evaluatesize()to be same value for multiple keys.The javadoc states:
If you wish to have unique values you could use
AtomicIntegercounter.