1

所以我有这个代码,其中 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 中修复
4

2 回答 2

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()原子操作的使用。我们也乐观地创建了一个新的锁,但是如果我们失去了比赛条件,我们就把它扔掉,并使用比赛获胜者锁。

于 2014-10-03T15:33:58.220 回答
0

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

于 2014-10-07T19:58:40.590 回答