一尘不染

为什么要在SynchronizedMap或SynchronizedCollections上进行同步?

java

我指的是此处提出的问题,并使用作者代码示例,现在我的问题是

  1. 作者为什么要使用synchronized(synchronizedMap),真的有必要吗,因为syncedMap始终会确保没有两个线程试图对其进行read/put操作,Map那么为什么需要synchronize在该地图本身上进行操作呢?

非常感谢您的解释。


  public class MyClass {
  private static Map<String, List<String>> synchronizedMap =
      Collections.synchronizedMap(new HashMap<String, List<String>>());

  public void doWork(String key) {
    List<String> values = null;
    while ((values = synchronizedMap.remove(key)) != null) {
      //do something with values
    }
  }

  public static void addToMap(String key, String value) {
    synchronized (synchronizedMap) {
      if (synchronizedMap.containsKey(key)) {
        synchronizedMap.get(key).add(value);
      }
      else {
        List<String> valuesList = new ArrayList<String>();
        valuesList.add(value);
        synchronizedMap.put(key, valuesList);
      }
    }
  }
}

阅读 295

收藏
2020-12-03

共1个答案

一尘不染

为什么我们需要对其synchronizemap本身进行同步?

您可能需要在一个已经同步的集合上进行同步,因为您正在对该集合执行两个操作-在您的示例中,是a containsKey()然后是aput()。您试图在 _调用_集合的代码中防止竞争情况。另外,在这种情况下,该块还保护值,以便多个线程可以将其值添加到这些未同步的集合中。
__synchronized``ArrayList

如果您查看链接到的代码,他们将首先检查键的存在,如果键不存在,则将值放入映射中。您需要防止2个线程的一个重要的生存确认,然后 两个
人投入的地图。比赛是哪一个将第一名,哪个人将覆盖前一名。

同步的集合可保护自己免受多个线程破坏映射本身的侵害。它 不能 防止围绕多次调用该映射的逻辑竞争条件。

synchronized (synchronizedMap) {
    // test for a key in the map
    if (synchronizedMap.containsKey(key)) {
      synchronizedMap.get(key).add(value);
    } else {
      List<String> valuesList = new ArrayList<String>();
      valuesList.add(value);
      // store a value into the map
      synchronizedMap.put(key, valuesList);
   }
}

这是ConcurrentMap接口具有的原因之一putIfAbsent(K key, V value);。但这 并不
需要两个操作,所以你可能并不需要围绕它同步。

顺便说一句,我将上面的代码重写为:

synchronized (synchronizedMap) {
    // test for a key in the map
    List<String> valuesList = synchronizedMap.get(key);
    if (valueList == null) {
      valuesList = new ArrayList<String>();
      // store a value into the map
      synchronizedMap.put(key, valuesList);
    }
    valuesList.add(value);
}

最后,如果地图上的大多数操作synchronized无论如何都需要位于一个块中,那么您不妨为支付费用,synchronizedMap而只需HashMapsynchronized块中始终使用。

2020-12-03