在Collections.synchronizedmap上同步

时间:2014-08-11 20:26:45

标签: java collections hashmap hashtable synchronized

在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());

4 个答案:

答案 0 :(得分:3)

From the docs

  

由所有类"集合视图方法"返回的集合的迭代器方法返回的迭代器。 fail-fast :如果在创建迭代器之后的任何时候对Hashtable进行结构修改,除了通过迭代器自己的remove方法之外,迭代器将抛出{{3 }}。

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

答案 1 :(得分:3)

  

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

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

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

答案 2 :(得分:1)

  

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

不,你需要同步它。

原因:

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

  • 这是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 :(得分:0)

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