-2

好的,据我了解,最好创建一个final static用于同步的对象。

但是,我还读到如果对象引用没有改变,那么它不会有并发问题。

以下代码是否违反同步性?

class Foo {
    private static ArrayList<Client> clients = null;

    public Foo() {
        clients = new ArrayList<>();
        //add stuff to list here..
    }

    public void addClient(Client C) {
        synchronized(clients) {
            clients.add(C);
        }
    }
}

ArrayList如果客户端从未直接公开(仅通过 Getters 除外),我是否必须使客户端成为最终对象或创建最终对象?换句话说,我从不为 clients 数组提供 set 方法,因此引用永远不会改变。

4

3 回答 3

3

任何创建 Foo 实例的人都会new Foo()覆盖 clients 数组。它绝对不是线程安全的

于 2013-05-09T19:01:45.413 回答
2

如果您真的希望客户端是静态的,即所有 Foo 共享一个客户端列表,以便收集所有客户端的巨大列表,那么您只需初始化一次。

private static ArrayList<Client> clients = new ArrayList();

但是我怀疑您希望每个 Foo 有一个客户列表,在这种情况下,不要将其声明为静态的,并且为了清楚起见,将其声明为最终的。(还有一些奇怪的极端情况,你真的必须将它声明为 final,如 Java Concurrency in Practice 中所述。)

于 2013-05-09T19:02:09.030 回答
1

为了使其线程安全,更改“客户”的声明,如下所示:

private final static List<Client> clients = new ArrayList<Client>();

并像你已经做的那样使用“同步”。

如果您对 static 关键字的含义感到困惑: static 关键字意味着 Foo 的所有实例将共享相同的“客户端”实例。如果删除 static 关键字,每个 Foo 实例都将拥有自己的“客户端”实例。

final 关键字只是阻止您重新分配 clients 变量。

于 2013-05-09T19:10:16.767 回答