请解释这个假如缺席的成语中的竞争状况

时间:2012-06-29 13:03:29

标签: java concurrency synchronization race-condition java.util.concurrent

请考虑以下代码,并假设该列表是同步列表。

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

if(!list.contains(element)){
       list.add(element)
}

我知道上面的代码片段需要在外部进行同步(由锁保护)以使其完全是线程安全的。竞争条件是否在这里?

5 个答案:

答案 0 :(得分:3)

实际上有很多。在评估contains时,列表可能会发生变异,当您到达add时,某人可能已添加该元素并再次添加该列表。此外,如果没有同步,整个事情可能会以奇怪的方式崩溃,因为其他线程的写入可能会被您的线程部分地,无序地或根本不被观察到。

如果containsadd本身是原子的(同步的),那么至少在调用containsadd之间会有一个明确定义的竞赛。< / p>

答案 1 :(得分:2)

好吧,假设两个线程执行检查并且都输入条件语句。然后两者都会将相同的元素添加到列表中,这不是预期的行为。不是吗?

答案 2 :(得分:2)

想象一下,你有两个线程

A: if(!list.contains(element)){ // false
B: if(!list.contains(element)){ // false
A:     list.add(element) // add once
B:     list.add(element) // add a second time.

当然,简单的解决方案是使用Set。 e.g。

Set<E> set = Collections.newSetFromMap(new ConcurrentHashMap<E, Boolean>());

set.add(element);

答案 3 :(得分:0)

当你获得列表并重新保存它时(如果保存到文件示例),竞争条件会发挥作用。

示例:文件包含A

  • 主题1获取A
  • 线程1将B添加到A
  • 线程2获取A
  • 主题1将AB保存到文件
  • 线程2将C添加到A
  • 线程2将AC保存到文件

读取文件将包含AC,而工作线程1将丢失

答案 4 :(得分:0)

我看到它的方式,竞争条件发生,如果list.contains(element)产生错误,另一个线程将在此之后但在第一个线程中添加调用之前添加元素。