不同步Java集合的后果
我想知道不同步Java中多个线程修改的集合可能产生的最坏后果是什么(除了数据损坏) 例如,线程的数量可以超过10个,集合(HashSet)可以增长到大约100000个元素(甚至更多)不同步Java集合的后果,java,multithreading,collections,deadlock,Java,Multithreading,Collections,Deadlock,我想知道不同步Java中多个线程修改的集合可能产生的最坏后果是什么(除了数据损坏) 例如,线程的数量可以超过10个,集合(HashSet)可以增长到大约100000个元素(甚至更多) 感谢因为HashSet在内部使用HashMap,所以您只需查看HashMap的putVal方法定义,并亲自查看—在执行该方法的任何时候,另一个线程都可能开始执行相同的操作。例如,它可以在调整大小时捕获数据,这意味着数据可能会写入旧表,或者同时创建两个新表 结果总是数据损坏,在发生此类事件后甚至可能不起作用 由于Ha
感谢因为HashSet在内部使用HashMap,所以您只需查看HashMap的putVal方法定义,并亲自查看—在执行该方法的任何时候,另一个线程都可能开始执行相同的操作。例如,它可以在调整大小时捕获数据,这意味着数据可能会写入旧表,或者同时创建两个新表
结果总是数据损坏,在发生此类事件后甚至可能不起作用 由于HashSet在内部使用HashMap,您只需查看HashMap的putVal方法定义并亲自查看—在该方法执行的任何时候,另一个线程都可能开始执行相同的操作。例如,它可以在调整大小时捕获数据,这意味着数据可能会写入旧表,或者同时创建两个新表
结果总是数据损坏,在发生此类事件后甚至可能不起作用 如果一个线程正在迭代集合,而另一个线程正在修改集合,则可能会得到
ConcurrentModificationException
详细说明见HashSet
文档:
请注意,此实现是不同步的。如果多个线程同时访问哈希集,并且至少有一个线程修改该集,则必须在外部对其进行同步。这通常通过在自然封装集合的某个对象上进行同步来实现。如果不存在此类对象,则应使用Collections.synchronizedSet方法“包装”集合。最好在创建时执行此操作,以防止意外不同步地访问集合:
Set s=Collections.synchronizedSet(新HashSet(…)代码>
这个类的迭代器方法返回的迭代器是快速失效的:如果在迭代器创建后的任何时候,以迭代器自己的remove方法以外的任何方式修改集合,迭代器将抛出一个ConcurrentModificationException
。因此,在面对并发修改时,迭代器会快速、干净地失败,而不是在将来的不确定时间冒着任意、不确定行为的风险
请注意,无法保证迭代器的快速失效行为,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬保证。Fail fast迭代器尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测bug
如果其中一个线程正在迭代集合,而另一个线程正在修改集合,则可能会得到ConcurrentModificationException
详细说明见HashSet
文档:
请注意,此实现是不同步的。如果多个线程同时访问哈希集,并且至少有一个线程修改该集,则必须在外部对其进行同步。这通常通过在自然封装集合的某个对象上进行同步来实现。如果不存在此类对象,则应使用Collections.synchronizedSet方法“包装”集合。最好在创建时执行此操作,以防止意外不同步地访问集合:
Set s=Collections.synchronizedSet(新HashSet(…)代码>
这个类的迭代器方法返回的迭代器是快速失效的:如果在迭代器创建后的任何时候,以迭代器自己的remove方法以外的任何方式修改集合,迭代器将抛出一个ConcurrentModificationException
。因此,在面对并发修改时,迭代器会快速、干净地失败,而不是在将来的不确定时间冒着任意、不确定行为的风险
请注意,无法保证迭代器的快速失效行为,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬保证。Fail fast迭代器尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测bug
最糟糕的结果是,您的数据结构最终指向自身,例如Java 7的HashMap可能会进入无限循环。因此,这意味着您不会得到错误,而您的线程永远不会返回。最糟糕的结果是您的数据结构最终指向自身,例如Java 7的HashMap可能会进入无限循环。因此,这意味着您不会得到错误,而您的线程永远不会返回。您将得到损坏的数据,并且无法信任。HashMap
您可能会得到一个死循环。@请您再解释一下。这有点像一个无限循环吗?@filip你不必提及集合不会被正确修改,这是众所周知的。也称为“您的数据已损坏”。还有什么可能比这更糟糕的呢?您将得到损坏的数据,而这些数据是无法信任的,因为HashMap
您可能会得到一个死循环。@请您再解释一下。这有点像一个无限循环吗?@filip你不必提及集合不会被正确修改,这是众所周知的。也称为“您的数据已损坏”。还有什么比这更糟糕的呢?