【问题标题】:Synchronizing nested Maps and Sets (Java)同步嵌套的 Map 和 Set (Java)
【发布时间】:2011-08-18 06:29:05
【问题描述】:

我在试图通过两个线程同步的地图中的地图内有一个嵌套集。

地图是这样实例化的:

private final Map<Manageable, Map<String, Set<Manageable>>> manageableMap = 
        Collections.synchronizedMap(new HashMap<Manageable, Map<String, Set<Manageable>>>());

这是我用来向地图添加值的函数:

private void put(Manageable key, Manageable value, String valueType) {
    synchronized (manageableMap) {
        Map<String, Set<Manageable>> setMap = manageableMap.get(key);
        if (setMap == null) {
            setMap = new HashMap<String, Set<Manageable>>();
            manageableMap.put(key, Collections.synchronizedMap(setMap));
        }

        synchronized (setMap) {
            Set<Manageable> set = setMap.get(valueType);
            if (set == null) {
                set = new HashSet<Manageable>();
                setMap.put(valueType, Collections.synchronizedSet(set));
            }

            synchronized (set) {
                set.add(value);
            }
        }
    }
}

Intellij IDEA 警告我正在对局部变量 setMap 和 set 进行同步。

我对同步相当陌生,我想知道这是否是正确的方法 像这样同步一个嵌套的数据结构。

感谢您的帮助。

【问题讨论】:

    标签: java map synchronization nested set


    【解决方案1】:

    您只需要在 manageableMap 上进行同步。一次只有1个线程可以获取manageableMap上的锁,所以如果一个线程已经获取了manageableMap上的锁,则不需要进一步锁定set和setMap,因为只有1个线程(锁定manageableMap的线程)可以访问set和setMap .

    【讨论】:

    【解决方案2】:

    同步作用于特定的对象实例,而不是作用于对它们的引用的字段或变量,因此您必须确保同步发生在相同的对象实例上,无论它们是否仅由局部变量引用。

    在这种特殊情况下,IDEA 无法静态检查代码是否符合您的要求,警告只是某种“代码气味”,警告您效果可能不符合预期。

    最好的办法是您通过注销您正在同步的实例来测试您的代码并检查它们是否是您期望的 - IDEA 还可以在调试期间标记对象实例以检查您同步的对象是否是相同或不同的实例。

    【讨论】:

      【解决方案3】:

      如果您总是手动控制同步,您可能不需要使用 Collections.synchronizedMap。在目标地图上同步一个部分即可。

      【讨论】:

      • 哪种方式更好,或者我应该说更有效:Collections.synchronizedMap 还是 Synchronized blocks?
      • synchronizedMap 在委托给包装地图的所有操作中都包含 synchronized(this)。如果此方法是您向地图添加元素的唯一地方,那么您不需要使用同步地图,只需使用常规地图即可。至于性能,我猜使用普通地图的版本会更有效 - 取决于使用模式。
      猜你喜欢
      • 2012-05-09
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      相关资源
      最近更新 更多