2016-09-27 94 views
3

如果我有这样的事情snippet-同步同步列表

public List<E> list = Collections.synchronizedList(new ArrayList<E>()); 

然后,如果我做的方法中的一些操作 -

boolean absent = !list.contains(x);    // Statement 1 
if(absent)          // Statement 2 
    list.add(x);        // Statement 3 

做我需要包装内synchronized(list){ ... }上述语句进行操作atomic

+1

我不认为这个问题是链接给出的倍数。这一个请求同步列表中的代码块,而另一个则是同步单个方法调用。即使他们的答案是不同的(必要的,而不是其他的)。 – uoyilmaz

+1

@uoyilmaz这是一个规范,涵盖了使用'synchronized'和'synchronizedList'方法的用例。和[answers](http://stackoverflow.com/a/9468329/1743880)也涵盖了这一点:*如果该块在列表上执行多个操作[...],那么同步并不是多余的* – Tunaki

回答

3

我是否需要将上述语句包装到synchronized(list){ ... }以使操作原子化?

是否则你的List可以调用containsadd的时间窗口可能导致竞争条件问题内你的代码的其他地方进行修改。

它使我的事情然后有什么用 Collections.synchronizedList

Collections.synchronizedList让您的List线程安全的,这样你可以同时修改,但仍然是所有方法调用自动执行。在上面的情况下,您需要拨打containsadd您必须以原子方式执行,否则如果其他地方我们称addcontains的结果可能会过时,这将导致竞争条件问题。防止竞争状态问题的唯一方法是在您的案例中使用list相同的对象监视器上的同步块。

+0

它使我那么想想Collections.synchronizedList的用法是什么? –

+0

@ShirgillFarhanAnsari假设两个线程并行调用remove()。如果你的基础列表不同步,有趣的事情会发生。重点是防止**独立**更改并行发生同步列表时发生问题。你正在谈论一组“呼之欲出”的电话! – GhostCat

+1

感谢您的帮助。我碰巧看到你的个人资料。你就像我一样认为这是JEE。它从来没有/是JEE。我的JavaEE正在由Web应用专家BalusC(JSF 2.3专家组成员)纠正。 –

1

正确。理论上,你的陈述1和3之间可能会发生任何事情;因此:如果你想让它们发生“原子”;那么你需要一些把它们变成“单笔交易”的方式。

使用synchronized(list)是一种合理的方法。

2

是的,同步列表使得方法调用是原子的,但是如果你想让多个语句成为原子的话(例如,当遍历列表等)时,你需要同步访问。