我有一个具有巨大静态数据结构的类。许多线程可能会并行读取它。我建议使用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);
任何详细解释的链接都应该有用。
谢谢,
答案 0 :(得分:3)
如果你想保护所有的小地图,那么无论何时你操纵它们,你都需要锁定大地图(或其他一些方便的全局可访问对象)。只访问大地图的单一方法调用很好,因为它是同步的。但第一次呼叫需要,即
synchronized(HashSets) {
if (HashSets.get(lang).contains(st)) ...
}
当您在迭代任何地图的键时,您还需要锁定大地图,否则您将冒ConcurrentModificationException
的风险。
正如另一张海报所指出的,这不是一个很好的设计。即使你使它工作,性能也会很差,因为单个大锁会大大降低并发性。 ConcurrentHashMap
持ConcurrentHashMap
个{{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