【问题标题】:Synchronizing a synchronized List [duplicate]同步一个同步列表 [重复]
【发布时间】:2016-09-27 10:30:19
【问题描述】:

如果我有这样的sn-p-

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 的操作吗?

【问题讨论】:

  • 我不认为这个问题是链接中给出的问题的倍数。这个要求同步列表中的代码块,而另一个是关于同步单个方法调用。甚至他们的答案也不同(对此有必要,对另一个没有必要)。
  • @uoyilmaz 这是一个规范,涵盖了使用synchronizedsynchronizedList 方法的用例。而answers 也涵盖了这一点:如果块在列表上执行多个操作 [...] 那么同步不是多余的

标签: java multithreading


【解决方案1】:

我是否需要将上述语句包装在synchronized(list){ ... } 中以使操作具有原子性?

是的,否则您的 List 可能会在您调用 containsadd 的时间窗口内被修改代码中的其他位置,这可能会导致竞争条件问题

它让我觉得有什么用 Collections.synchronizedList?

Collections.synchronizedList 使您的List 线程安全,这样您就可以同时修改它,但所有方法调用仍然以原子方式执行。在上述情况下,您调用containsadd,您必须以原子方式执行,否则如果在其他地方我们调用addcontains 的结果可能会过时,这将导致竞争条件问题。防止竞争条件问题的唯一方法是在同一对象监视器上使用同步块,在您的情况下为 list

【讨论】:

  • 这让我想到Collections.synchronizedList有什么用?
  • @ShirgillFarhanAnsari 假设两个线程并行调用 remove()。如果您的基础列表不同步,就会发生有趣的事情。关键是防止同步列表的独立更改并行发生时出现问题。你在谈论一组“属于一起”的电话!
  • 感谢您的帮助。我碰巧看到了你的个人资料。你就像我一样认为它是JEE。它从来不是/曾经是 JEE。 Web 应用程序专家 BalusC(JSF 2.3 专家组成员)为此更正了它的 JavaEE。
【解决方案2】:

是的,同步列表使方法调用原子化,但如果您想使多个语句原子化(例如,在迭代列表时等),则需要同步访问。

【讨论】:

    【解决方案3】:

    正确。从理论上讲,您的陈述 1 和 3 之间可能发生任何事情;因此:如果您希望它们发生“原子”;那么你需要某种方式将它们变成“单一交易”。

    使用synchronized(list) 是实现目标的合理方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 2018-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多