在Java中,我需要声明我的收藏同步,如果它的只读?(In Java, do I need to d

2019-08-17 08:25发布

我填的集合一次性J2EE我的web应用程序启动时。 然后,几个线程可以同时访问它,但只有阅读它。

我知道使用同步采集是强制性的相似之处写字,但我还需要它的相似之处读?

Answer 1:

通常情况下没有,因为你并没有改变在这种情况下,集合的内部状态。 当你遍历集合创建迭代器的一个新实例和迭代的状态是每个迭代器实例。


除了注意:请记住,通过保持一个只读集合你只防止修改集合本身。 每一个集合元素仍然是可变的。

class Test {
    public Test(final int a, final int b) {
        this.a = a;
        this.b = b;
    }

    public int a;
    public int b;
}

public class Main {

    public static void main(String[] args) throws Exception {
        List<Test> values = new ArrayList<Test>(2);
        values.add(new Test(1, 2));
        values.add(new Test(3, 4));

        List<Test> readOnly = Collections.unmodifiableList(values);
        for (Test t : readOnly) {
            t.a = 5;
        }

        for (Test t : values) {
            System.out.println(t.a);
        }
    }

}

这种输出:

5
5

从@WMR answser重要的考虑因素。

这取决于是否正在读取您的收藏线程之前或您填写之后开始。 如果他们开始填写之前,你有没有保证(不同步),这些线程永远不会看到更新的值。

这样做的原因是Java内存模型,如果你想知道更多,在此链接阅读节“可见性”: http://gee.cs.oswego.edu/dl/cpj/jmm.html

而且,即使线程开始您填写您的收藏后,您可能需要同步,因为您的收藏实现可以在读操作时甚至改变其内部状态(感谢迈克尔·巴尔-西奈 ,我不知道这样的集合存在)。

在并发的涵盖主题,如物体的出版,能见度等,更详细的话题另一个非常有趣的阅读是布赖恩戈茨的书Java并发实践 。



Answer 2:

这取决于是否正在读取您的收藏线程之前或您填写之后开始。 如果他们开始填写之前,你有没有保证(不同步),这些线程永远不会看到更新的值。

这样做的原因是Java内存模型,如果你想知道更多,在此链接阅读节“可见性”: http://gee.cs.oswego.edu/dl/cpj/jmm.html

而且,即使线程后您填写您的收藏开始,你可能需要同步,因为您的收藏实施可能会改变,甚至在读操作时其内部状态(感谢迈克尔·巴尔-西奈 ,我不知道在标准JDK中存在这样的收藏)。

在并发的涵盖主题,如物体的出版,能见度等,更详细的话题另一个非常有趣的阅读是布赖恩戈茨的书Java并发实践 。



Answer 3:

在一般情况下,你应该。 这是因为一些藏品改变其内部结构中读取。 使用访问顺序LinkedHashMap中是一个很好的例子。 但是,不要只相信我的话:

在访问顺序链接的哈希映射中,仅查询与获取地图是一个结构修改链接的散列图的Javadoc

如果你有绝对的把握,有没有缓存,没有收集统计​​数据,没有优化,没有有趣的东西在所有 - 你并不需要同步。 在这种情况下,我将不得不把一个类型约束的集合:不要声明收集的地图(这将使LinkedHashMap的),但作为HashMap中(对于纯粹主义者,HashMap中的最终子类,但可能是太把它远...)。



Answer 4:

你不必到,在其他的答案解释。 如果你想确保你的集合为只读,你可以使用:

yourCollection = Collections.unmodifableCollection(yourCollection);

(类似的方法列表中存在,设置,地图和其他集合类型)



Answer 5:

集合本身不对,但请记住,如果它认为并不是一成不变也是,那些单独的班级需要自己的同步。



文章来源: In Java, do I need to declare my collection synchronized if it's read-only?