我想将预先构建的Map传递给多个线程,这些线程只会同时从Map中读取值。在这种情况下,我是否需要担心并发访问并使用ConcurrentHashMap而不是HashMap?
答案 0 :(得分:6)
您仍然需要确保创建和初始化Map的线程与随后读取它的线程之间存在“before-before”关系。如果没有这样的关系,理论上可能读取线程看到陈旧数据。
如果您在启动其他线程的线程中创建并填充Map ...在它执行此操作之前......您应该没问题。
另一种确保安全的简单方法是做这样的事情:
public class Foo {
private final Map map;
public Foo(....) {
map = new HashMap();
// populate
}
public Map getMap() {
// If the 'map' is final, and nothing changes it apart from
// the constructor, this method doesn't need to be synchronized.
}
这两个都会导致创建/初始化与每个线程首次使用Map之间的“先发生”关系。
你也可以在上面声明map
为volatile
,但可能会导致更多的缓存刷新而不是严格需要发生;也就是说你会受到很小的打击。
答案 1 :(得分:3)
另外,为了确保仅为阅读操作处理,您可以做的是返回Collections.unmodifiableMap(Map)。
答案 2 :(得分:2)
理论上,并发阅读不应该导致收藏问题。
但是如果你修改它一次,它很容易出错,然后你应该使用并发版本。
答案 3 :(得分:2)
如果所有线程都在读取HashMap,则传递HashMap是安全的。但是,在传递map之前,我会调用Collections.unmodifiableMap()来确保如果某个线程意外地修改了它,因为将来某个程序员不尊重当前的合同,你将获得异常。
答案 4 :(得分:2)
您始终需要担心线程安全问题。在您的具体示例中,如果您
就足够了volatile
变量来引用它来将其发布到其他线程。或者,如果这是一个选项,请确保在地图准备好之前不会启动线程。
答案 5 :(得分:1)
否,你不必担心。
除非有人在线程访问时更改预先构建的地图。
答案 6 :(得分:1)
不,你不需要使用它。仅在以下情况下才会生成冲突:
当每个线程只是尝试读取值时,不会产生冲突。