2014-03-13 44 views
3

我有一个ArrayList,我只在同步块内操作它,我是否也应该使用Collections.synchronizedList? 例子:Java:同步列表

List list = Collections.synchronizedList(new ArrayList());  
// versus List list = new ArrayList();  
synchronized(list) { 
     // my code 
} 
+0

只有一个就足够了两个synchronizedList()synchornized块。只使用'synchronizedList' – rzymek

回答

1
  • 如果你只在​​阻止访问列表,你不需要synchronizedList()

  • 如果你只使用访问基本运算(add()remove()等),以及这些操作的唐调用列表“T彼此依赖(即原子性不是问题),如果你希望能够调用基本操作只能使用synchronizedList()没有明确​​块

  • withou牛逼​​块,也有复合操作(包括迭代)应该是原子,你需要混合操作

+0

非基本操作只是迭代?我总是只看到这些例子,而不是其他的,所以,“只是为了迭代而阻止”? – Tatanan

+1

可能有复合操作也应该是原子的,比如'if(!list.contains(...))list.add(...)' – axtavt

+0

@Tata​​nan,“不是基本的”意思是任何操作序列暂时使您的数据处于不一致/无效/非法状态。典型的例子是从一个银行账户中取钱并存入另一个账户的程序。当书籍不正确时,在提款和存款之间有一个瞬间。如果审计员线程在该瞬间恰好看到两个账户,它将报告违规行为。将这两个操作放到同步块中会使它们成为一个原子单位,并且会阻止审计人员看到处于该状态的帐户。 –

1

只需使用synchronized声明,不需要明确的同步块:

List list = Collections.synchronizedList(new ArrayList()); 

更改列表中的内容的唯一方法是通过调用添加或删除,这是现在由于这个声明而用这些方法的同步版本进行了修饰。

+1

我认为块是迭代,排序等所必需的。 我的怀疑实际上只是声明,如果万一我把我所有的代码包装,我需要声明列表为同步。 – Tatanan

1

使用明确的​​块和使用Collections.synchronizedList(new ArrayList())将等效于互斥。但是,如果你必须遍历由调用返回的Collections列表中,您必须名单上显式同步外部反正每Java规范(对不起,SO不会让我链接到它这里) 。

要考虑的另一件事是开销。 Collections.synchronizedList(List orig)创建一个新的对象来控制对原始列表实现的访问。根据您计划进行此调用的频率以及您访问原始列表对象的方式有多种,您可能最好在外部同步它。