Reputation: 55
So I have this code where lockMap is a ConcurrentHashMap
//Creation of locks
Lock getLock(String key) {
Lock lock = lockMap.get(key);
if (lock == null) {
synchronized (lockMap) {
lock = lockMap.get(key);
if (lock == null) {
lock = new ReentrantLock();
lockMap.put(key, lock);
}
}
}
return lock;
}
During a code review someone mentioned that this is a typical case of DCL, because, since the compiler can reorder events, it is possible that the lock is not yet fully initialized when inserted in the map, then the next thread requesting the same lock could potentially not yet be fully initialized.
Now, the problem I have with this is that this problem is a common problem with multi threaded applications: get something from a map and if not there create and add.
Upvotes: 1
Views: 241
Reputation: 55
So somehow i did not get any notifications so sorry about the late response. I thought of the put if absent, however, there is a cost of always creating an object for nothing (most of the time) so i wanted to avoid this. but i guess the cost is minimal so i will use this solution.
Upvotes: 0
Reputation: 17707
The fact that you have locks in a ConcurrentHashMap is.... confusing, but, assuming you know what you are doing with them, the better way to write this would be:
Lock getLock(String key) {
Lock lock = lockMap.get(key);
if (lock == null) {
lock = new ReentrantLock();
Lock race = lockMap.putIfAbsent(key, lock);
if (race != null) {
//there was a race, we lost.
lock = race;
}
}
return lock;
}
Note the use of the putIfAbsent() atomic operation. We also optimistically create a new Lock, but then if we lost the race-condition, we throw it out, and use the race winner lock.
Upvotes: 2