【问题标题】:synchronizing on Collections.synchronizedmap在 Collections.synchronizedmap 上同步
【发布时间】:2014-10-04 18:51:35
【问题描述】:

在 Collections javadoc 中如下所述..

当迭代其任何集合视图时,用户必须在返回的地图上手动同步:

Map m = Collections.synchronizedMap(new HashMap());
      ...
  Set s = m.keySet();  // Needn't be in synchronized block
      ...
  synchronized (m) {  // Synchronizing on m, not s!
      Iterator i = s.iterator(); // Must be in synchronized block
      while (i.hasNext())
          foo(i.next());
  }

我的问题是,如果我声明了一个 Hashtable,我可以在不同步的情况下使用它。 如下所示

  Hashtable ht = new Hashtable();
     Set s = m.keySet();

 Iterator i = s.iterator();
          while (i.hasNext())
              foo(i.next());

【问题讨论】:

  • Hashtable 不是同步地图。请改用ConcurrentHashMap
  • @LuiggiMendoza 这是一张地图,它是同步的。怎么不是同步地图?
  • 你在哪里使用ht
  • 我认为您不了解线程安全性和一致性的根本不同点。当然,您可以不同步地循环,也可以对同步的HashMap 执行相同的操作。但生成的输出只会与Map 中的内容略微一致。 ConcurrentHashMap 没有区别。
  • 看能否被其他线程修改。

标签: java collections hashmap hashtable synchronized


【解决方案1】:

当您在单个线程中执行每个操作时,在这种情况下应该没有观察到并发问题。尽管我必须说您从 JavaDoc 提供的示例与您有疑问的示例无关。请修改问题并提供更多详细信息。

【讨论】:

    【解决方案2】:

    如果我声明了一个 Hashtable,我可以在不同步的情况下使用它吗?

    不,你需要同步它。

    原因:

    • 在 Java 中对 [any] 集合的迭代不是线程安全的。

    • 这是 Hashtable#keyset() 方法的实现: public Set<K> keySet() { if (keySet == null) keySet = Collections.synchronizedSet(new KeySet(), this); return keySet; } 如果您注意到,它会返回 synchronizedSet。正如 javadoc It is imperative that the user manually synchronize on the returned set when iterating over it 中提到的那样,因为 SyncronizedSet 中的 iterator 方法未同步。

    【讨论】:

      【解决方案3】:

      如果我声明了一个 Hashtable 并且我可以在不同步的情况下使用它。

      你可以,但如果你想避免 ConcurrentModificationException,你不应该这样做。 IE。它使用同步就像同步的 HashMap 一样有同样的限制。

      注意:如果你使用 ConcurrentHashMap,你不需要锁定它(事实上你不能)

      【讨论】:

        【解决方案4】:

        是的。

        From the docs:

        该类的所有“集合视图方法”返回的集合的迭代器方法返回的迭代器是fail-fast:如果在创建迭代器后的任何时间对哈希表进行结构修改, 除了通过迭代器自己的 remove 方法外,迭代器将抛出一个ConcurrentModificationException

        因此,如果您想通过 Hashtable 的迭代器,您必须确保同时没有其他人修改 Hashtable 对象。如果该对象在多个线程之间共享,那么最好的方法是在一个公共对象上进行同步,例如您正在迭代的同一 Hashtable

        【讨论】:

          猜你喜欢
          • 2010-10-08
          • 1970-01-01
          • 2014-04-27
          • 1970-01-01
          • 1970-01-01
          • 2019-08-26
          • 2010-12-07
          • 2012-02-11
          • 2016-01-29
          相关资源
          最近更新 更多