同步非最终列表

问题描述:

好吧,据我了解,它最好创建一个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永远不会(通过吸气剂仅除外)直接暴露?换句话说,我从不为客户端数组提供set方法,因此引用永远不会改变。

+1

如果引用没有改变,那么为什么不把它作为最终的? – 2013-05-09 19:00:50

+1

我在这里没有看到问题,但为什么不直接让它最终呢? – Nick 2013-05-09 19:01:11

+0

我在C++中认为final = const,所以如果我这样做,我不能添加任何东西。但谷歌搜索后,我看到它不一样。 – Brandon 2013-05-09 19:02:22

任何创建Foo new Foo()实例的人都会覆盖客户端阵列。它绝对不是线程安全的

+0

How:S它是一个静态数组。 – Brandon 2013-05-09 19:02:57

+0

是静态的并不意味着它不能被分配。你想要的是它是最终的。但是如果你把它设为静态的最终结果比上面的代码不会编译,因为你不能对同一个成员进行2个赋值(第一个空值比实际的数组) – Asaf 2013-05-09 19:04:17

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

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

但我怀疑,你想每一个富客户名单,在这种情况下,声明它的静态和,为清楚起见,做到声明它决赛。 (也有一些奇怪的角落情况下,你真的必须声明为final,因为在实践中的Java并发描述。)

+0

是的:)我想要一个列表所有的Foos,所以我让它静态。我像你的初始化它,并将其作为最终。我不确定,因为在C++中,我只能在构造函数或初始化列表中进行初始化。仍在学习java。这是一个很好的功能。谢谢! – Brandon 2013-05-09 19:13:53

为了使线程安全变革的“客户”像这样的声明:

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

并且像你已经做的那样使用'synchronized'。

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

final关键字只会阻止您重新分配客户端变量。