我在初始化时完全加载了一个java HashMap,但在初始化之后,多个线程将从HashMap读取数据。我希望避免任何类型的同步,因为映射本质上是只读的,并且永远不会更改。但是我能保证所有的键和值对所有线程都是可见的吗?
发布于 2011-03-02 14:46:55
如果地图的内容永远不变,那么您就没有问题。只有当变量的内容发生变化时,内存模型可见性问题才会发挥作用。
您可能希望同步映射的初始化,以确保在映射完全初始化之前没有线程访问它,并确保加载到映射中的所有值都可见。
编辑:最初,我完全忽略了map如何初始化的问题。在(再次)读取one of the Pugh articles之后,似乎映射确实需要是最终的,才能使初始化数据变得可见:
能够看到字段的正确构造的值是很好的,但是如果字段本身是一个引用,那么您还希望您的代码能够看到它所指向的对象(或数组)的最新值。如果您的字段是最终字段,这也是有保证的。因此,您可以有一个指向数组的最终指针,而不必担心其他线程看到数组引用的正确值,但看到数组内容的错误值。同样,这里所说的“正确”,我们指的是“对象构造函数结束时的最新值”,而不是“可用的最新值”。
在Java规范中有一个强制“发生-之前”关系的条件列表,我应该在这里引用它们(或者如果其他人在他们的答案中这样做,我会投票支持它)。静态变量和Holder习惯用法当然是一种方法。这个问题非常广泛,因为它没有指定map是如何初始化的,如果你发布了一个问题来描述你打算如何进行初始化,你可能会得到一个更直接的有用的答案。
发布于 2011-03-02 14:57:11
如果您将HashMap声明为final,并且预初始化一个本地HashMap,然后将全局HashMap与本地一起存储,则在构造函数初始化之后,HashMap的内容将变为可见。
必须正确使用
Final字段以提供不可变性的保证。当一个对象的构造函数完成时,它被认为是完全初始化的。只有在对象完全初始化后才能看到对该对象的引用的线程,一定会看到该对象的最终字段的正确初始化值。
发布于 2011-03-02 14:47:06
从Guava使用ImmutableMap将是最好的解决方案。
https://stackoverflow.com/questions/5169101
复制