在Java中,如果集合是只读的,我是否需要声明其集合已同步? [英] In Java, do I need to declare my collection synchronized if it's read-only?

查看:82
本文介绍了在Java中,如果集合是只读的,我是否需要声明其集合已同步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我的J2EE Webapp启动时,我一次填充了一个集合. 然后,几个线程可能会同时访问它,但只能读取它.

I fill a collection one single time when my J2EE webapp starts. Then, several thread may access it at same time but only to read it.

我知道对于并行写入必须使用同步集合,但是对于并行读取仍需要它吗?

I know using a synchronized collection is mandatory for parallels write but do I still need it for parallels read ?

推荐答案

通常不会,因为在这种情况下您不会更改集合的内部状态.在集合上进行迭代时,将创建一个新的迭代器实例,并且迭代状态是每个迭代器实例.

Normally no because you are not changing the internal state of the collection in this case. When you iterate over the collection a new instance of the iterator is created and the state of the iteration is per iterator instance.

旁注::请记住,通过保留只读集合,您只能防止对集合本身进行修改.每个集合元素仍然可以更改.

Aside note: Remember that by keeping a read-only collection you are only preventing modifications to the collection itself. Each collection element is still changeable.

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答案中的重要注意事项.


Important considerations from @WMR answser.

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

It depends on if the threads that are reading your collection are started before or after you're filling it. If they're started before you fill it, you have no guarantees (without synchronizing), that these threads will ever see the updated values.

原因是Java内存 模型,如果您想了解更多信息,请阅读 此链接的可见性"部分: http://gee.cs.oswego.edu/dl/cpj/jmm. html

The reason for this is the Java Memory Model, if you wanna know more read the section "Visibility" at this link: http://gee.cs.oswego.edu/dl/cpj/jmm.html

即使线程已启动 填写完收藏后,您 可能需要同步,因为您的 馆藏实施可能会改变 它的内部状态,即使在读取时 操作(感谢迈克尔 Bar-Sinai , 我不知道这样的收藏 存在).

And even if the threads are started after you fill your collection, you might have to synchronize because your collection implementation could change its internal state even on read operations (thanks Michael Bar-Sinai, I didn't know such collections existed).

另一本非常有趣的文章 并发主题,涵盖 诸如发布对象之类的话题, 可见性等更多详细信息 是Brian Goetz的书 Java 并发 练习.

Another very interesting read on the topic of concurrency which covers topics like publishing of objects, visibility, etc. in much more detail is Brian Goetz's book Java Concurrency in Practice.

这篇关于在Java中,如果集合是只读的,我是否需要声明其集合已同步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆