不同步Java集合的后果

时间:2016-09-22 08:41:37

标签: java multithreading collections deadlock

我想知道不同步由Java中的多个线程修改的集合的最糟糕的后果(除了数据损坏)。

真实的例子,线程数可以大于10,集合(HashSet)可以增长到大约100 000个元素(甚至更多)。

由于

3 个答案:

答案 0 :(得分:2)

由于HashSet在内部使用HashMap,您可以查看HashMap的putVal方法定义并亲自查看 - 在执行该方法的任何时候,另一个线程可能会开始这样做。例如,它可以在调整大小时捕获它,这意味着可以将数据写入旧表,或者同时创建两个新表。

结果总是数据损坏,在发生此类事件后甚至可能无法正常工作。

答案 1 :(得分:1)

如果其中一个线程正在迭代该集合而另一个线程正在修改它,则可能会得到ConcurrentModificationException

详细说明见HashSet文档:

  

请注意,此实现未同步。如果多个线程同时访问哈希集,并且至少有一个线程修改了该集,则必须在外部进行同步。这通常通过在自然封装集合的某个对象上进行同步来实现。如果不存在这样的对象,那么该集合应该是" wrap"使用Collections.synchronizedSet方法。这最好在创建时完成,以防止意外地不同步访问集:

     

Set s = Collections.synchronizedSet(new HashSet(...));

     

此类的迭代器方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时间修改集合,除了通过迭代器自己的删除方法之外,迭代器抛出ConcurrentModificationException。因此,面对并发修改,迭代器会快速而干净地失败,而不是在未来不确定的时间冒着任意的,非确定性行为的风险。

     

请注意,迭代器的快速失败行为无法得到保证,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬性保证。失败快速的迭代器会尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应仅用于检测错误。

答案 2 :(得分:1)

最糟糕的是你的数据结构最终指向自身,例如HashMap到Java 7可能会进入无限循环。因此意味着你没有错误,而你的线程永远不会返回。