繁体   English   中英

在Collections.synchronizedmap上同步

[英]synchronizing on Collections.synchronizedmap

在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进行结构修改,则除了通过迭代器自己的remove以外,都可以通过其他方式进行修改方法,迭代器将抛出ConcurrentModificationException

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

如果我声明了Hashtable,并且可以不对其进行同步就使用它。

您可以,但如果不想避免ConcurrentModificationException,则不可以。 即,它使用同步就像具有相同限制的同步HashMap一样。

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

如果我声明了Hashtable,是否可以不对其进行同步而使用它?

不,您需要同步它。

原因:

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

  • 这是Hashtable#keyset()方法的实现: public Set<K> keySet() { if (keySet == null) keySet = Collections.synchronizedSet(new KeySet(), this); return keySet; } public Set<K> keySet() { if (keySet == null) keySet = Collections.synchronizedSet(new KeySet(), this); return 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方法未同步。

当您在单个线程中执行所有操作时,在这种情况下应该不会出现并发问题。 尽管我必须说您从JavaDoc提供的示例与您有疑问的示例无关。 请更详细地修改问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM