请考虑以下代码,并假设该列表是同步列表。
List list = Collections.synchronizedList(new ArrayList());
if(!list.contains(element)){
list.add(element)
}
我知道上面的代码片段需要在外部进行同步(由锁保护)以使其完全是线程安全的。竞争条件是否在这里?
答案 0 :(得分:3)
实际上有很多。在评估contains
时,列表可能会发生变异,当您到达add
时,某人可能已添加该元素并再次添加该列表。此外,如果没有同步,整个事情可能会以奇怪的方式崩溃,因为其他线程的写入可能会被您的线程部分地,无序地或根本不被观察到。
如果contains
和add
本身是原子的(同步的),那么至少在调用contains
和add
之间会有一个明确定义的竞赛。< / 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
读取文件将包含AC,而工作线程1将丢失
答案 4 :(得分:0)
我看到它的方式,竞争条件发生,如果list.contains(element)
产生错误,另一个线程将在此之后但在第一个线程中添加调用之前添加元素。