这个同步的代码真的在执行作者想要的吗?

时间:2018-09-28 16:13:49

标签: java synchronization

我正在研究一个我可以肯定它与时间相关的错误,因为它在多个线程中使用。我认为我发现了可能是一个问题的代码,但是我想知道是否可以验证我的想法。

请考虑以下代码段:

public MyClass {

    private Map<String, Map<String, String>> managedMap = Collections.synchronizedMap(new HashMap<>);

    public purgeOldData() {
      Map<String, Map<String, String>> cpyManagedMap = Collections.synchronizedMap(new HashMap<>(managedMap));

      cpyManagedMap.forEach((primaryKey, pkMap) -> {
        Map<String, String> cpyPkMap = new HashMap<>(pkMap);

        cpyPkMap.forEach((secondKey, value) -> {
            checkToPurge(primaryKey, pkMap, secondKey, value);
        });
      });
    }

    private checkToPurge(String primaryKey, Map pkMap, String secondKey, String value) {
        synchronized (managedMap) {
            if (someMethodThatReturnsBoolean()) {
                pkMap.remove(secondKey);

                if (pkMap.isEmpty()) {
                  managedMap.remove(primaryKey);
                }
            }
        }
    }
}

因此,managedMap是一个类成员,在整个类中都可以使用,必要时在同步块内使用。在purgeOldData()中,创建了ManagedMap的副本,并使副本同步。因此,cpyManagedMap是托管地图在特定时间的快照。

完成复制后,有几个循环可以最终获得我们要检查的数据。该数据被发送到checkToPurge()方法。在此方法内部,整个方法在原始ManagedMap上同步。

最后,我们回答了我的问题:

  1. 由于cpyManagedMap是及时的快照,难道不是在副本和checkToPurge()中的synch块之间的时间更新了ManagedMap吗?意味着该副本用于确定是否从原始ManagedMap中删除可能已更新的内容?

  2. 在这种情况下,真的需要同步cpyManagedMap吗?

  3. 如果确实我对mamagedMap可能被更新的担忧是真的,那么关于如何修复代码的任何建议?我是否应该将purgeOldData中的所有代码与managedMap同步?

谢谢!

0 个答案:

没有答案