java中Collections.synchronizedMap的基础知识

时间:2011-11-03 11:18:43

标签: java

我有一个具有巨大静态数据结构的类。许多线程可能会并行读取它。我建议使用Collections.synchronizedMap

私有静态地图< String,HashSet<字符串>> HashSets =     Collections.synchronizedMap(new HashMap< String,                                  HashSet<字符串>> ());

根据http://download.oracle.com/javase/6/docs/api/,我需要在访问值时使用synchronized()关键字。我不太了解它。

我应该如何修改以下访问:

if (HashSets.get (lang).contains (st))

if (HashSets.containsKey (lang) == false)

HashSets.put (lang, testhashset);

任何详细解释的链接都应该有用。

谢谢,

2 个答案:

答案 0 :(得分:3)

如果你想保护所有的小地图,那么无论何时你操纵它们,你都需要锁定大地图(或其他一些方便的全局可访问对象)。只访问大地图的单一方法调用很好,因为它是同步的。但第一次呼叫需要,即

synchronized(HashSets) {
    if (HashSets.get(lang).contains(st)) ...
}

当您在迭代任何地图的键时,您还需要锁定大地图,否则您将冒ConcurrentModificationException的风险。

正如另一张海报所指出的,这不是一个很好的设计。即使你使它工作,性能也会很差,因为单个大锁会大大降低并发性。 ConcurrentHashMapConcurrentHashMap个{{1}}会更好。

答案 1 :(得分:0)

规范页面试图说明的是,当您需要对返回的映射进行多次访问时,您必须进行同步(例如,迭代)。但单独的是线程安全和原子的。

所以在你的情况下,因为你只想在IF操作的条件适用时执行put,你应该将整个事件包装在synchronized {}中,如下所示:

synchronized(HashSets ){    
   if (HashSets.get (lang).contains (st))
      if (HashSets.containsKey (lang) == false)
         HashSets.put (lang, testhashset);
}

PS。您不应该使用以大写字符开头的变量作为变量名(常见约定)。 HashSets - > hashSets