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

Java 双重检查锁定的特殊情况?,java,multithreading,double-checked-locking,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) {

我有一段代码,其中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的典型情况,因为编译器可以对事件重新排序,因此在插入映射时锁可能尚未完全初始化,那么请求相同锁的下一个线程可能尚未完全初始化

现在,我遇到的问题是,这个问题是多线程应用程序的一个常见问题:从映射中获取一些东西,如果没有,则创建并添加

  • 这真的是DCL的案例吗
  • 如果是这样,你如何解决它。(我们使用的简单而愚蠢的方法是创建一个锁池,当从池中提取一个锁时,会插入一个新锁)
  • 如果是这样,它在java8中是固定的吗

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

    注意原子操作的使用。我们也乐观地创建了一个新的锁,但是如果我们失去了比赛条件,我们就会扔掉它,并使用比赛赢家锁。

    因此,不知何故,我没有收到任何通知,因此很抱歉响应太晚。 我想到了put if缺席,然而,总是免费创建一个对象是有成本的(大部分时间),所以我想避免这种情况。
    但是我想成本是最低的,所以我将使用这个解决方案。

    重新排序哪些事件?为什么要查询锁两次,为什么在字典中有锁?为了使整个操作有任何意义,应该首先获得一个不在字典中的锁,例如synchonized方法,然后在返回之前锁定锁。它是DCL,但是正如@rolfl所示,没有必要在
    ConcurrentHashMap
    上进行
    同步
    。另外,“它在java 8中是固定的”是什么意思?这与java.to-Vidstige的版本无关。映射操作是线程安全的。不是它周围的东西。使用相同密钥的2个线程将获得null。两者都创建锁,都在映射中安全地插入值,但在外部使用两个不同的锁,这是错误的。不会编译,因为没有返回任何内容