双重检查锁定的特殊情况?

时间:2014-10-03 15:28:54

标签: java multithreading double-checked-locking

所以我有这个代码,其中lockMap是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;
}

在代码审查期间,有人提到这是DCL的典型案例,因为,由于编译器可以对事件进行重新排序,因此当插入映射时锁可能尚未完全初始化,然后下一个线程请求相同的锁可能尚未完全初始化。

现在,我遇到的问题是这个问题是多线程应用程序的常见问题:从地图中获取内容,如果没有,则创建并添加。

  1. 这真的是DCL的情况吗?
  2. 如果是这样,你如何解决它。 (我们使用的简单和愚蠢的方法是创建一个锁池,当从池中提取一个锁时,会插入一个新的锁)。
  3. 如果是这样,是否在java8中修复了

2 个答案:

答案 0 :(得分:2)

你在ConcurrentHashMap中有锁的事实......令人困惑,但是,假设你知道你在做什么,最好的方法是:

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;
}

请注意putIfAbsent()原子操作的使用。我们也乐观地创造了一个新的锁,但如果我们失去了比赛条件,我们就把它扔出去,并使用比赛获胜者锁。

答案 1 :(得分:0)

所以不知怎的,我没有收到任何通知,对于迟到的回复感到遗憾。 我想到了如果不存在,但是,总是创造一个对象的成本(大部分时间),所以我想避免这种情况。 但我想成本很低,所以我会使用这个解决方案。