如果我有以下声明:
Map<String, Map<String, Person>> families =
Collections.synchronizedMap(new HashMap<String, Map<String, Person>>());如果我接着像这样打电话:
families.get(lastName).put(firstName, new Person());这个线安全吗?在我看来,这两张地图中只有一张是同步的,但是如果不经过外部同步映射,你就无法到达内部地图,所以我不确定.
编辑优秀的点,在这两个答案到目前为止,谢谢一堆!但现在我在想如果我这么做了
families.put(lastName, Collections.synchronizedMap(new HashMap<String, Person>());然后做了我的链式调用,整个链线程安全吗?是否有可能在get(lastName)和put(firstName, new Person())之间,另一个线程可以获得内部映射?我在想,如果我想要整个链条安全,我需要把它放在一个同步块中,但我也想知道这是否也会工作。
发布于 2011-01-27 07:39:19
完全有可能在调用外部get()和内部put()之间,一些其他线程也调用外部get()并获得相同的内部映射。但是由于它是同步的,所以无论如何它应该是安全的。
问题是当你把一些东西放进外部地图。线程如何确定是否需要创建新的内部映射?假设您有这样的代码:
if (!families.containsKey(lastName)) {
families.put(lastName, Collections.synchronizedMap(new HashMap<String, Person>());
}现在,这肯定是不安全的,因为其他线程可能同时做同样的事情,因此您最终创建了两个内部映射,其中一个立即成为垃圾收集的候选对象。
最好只是同步所有与整个结构一起工作的方法,而不使用同步映射。它可能也会更快,因为您只需要一个级别的同步。
发布于 2011-01-26 21:39:13
你可以通过同步的外部地图得到内部地图,但是你可以用它做你想做的事情。所以这不是线程安全。
如果您在这个场景中确实希望线程安全,我将创建一个包含映射映射的对象,然后您可以通过同步访问器来控制访问。我建议这是一个很好的实践,在大多数情况下,您可以组成集合集合。
发布于 2011-01-26 21:41:26
内部映射不是线程安全的。
如果其他线程做了
families.get(lastName).put(firstName, new Person());使用相同的lastName,一个线程就有可能获得内部映射,然后另一个线程获得内部映射,然后两个线程同时调用put并破坏一切。
使用synchronizedMap通常不足以实现正确的并发性--通常您希望显式地锁定每个事务,而不是围绕每个方法调用。
https://stackoverflow.com/questions/4810325
复制相似问题