Adrien
Adrien

Reputation: 55

Special case of double checked locking?

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.

  1. Is this really a case of a DCL?
  2. If so, how do you solve it. (easy and dumb way we used is to create a pool of locks and when one is extracted from the pool a new one is inserted)
  3. If so again, is it fixed in java8

Upvotes: 1

Views: 241

Answers (2)

Adrien
Adrien

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

rolfl
rolfl

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

Related Questions