Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
不同步Java集合的后果_Java_Multithreading_Collections_Deadlock - Fatal编程技术网

不同步Java集合的后果

不同步Java集合的后果,java,multithreading,collections,deadlock,Java,Multithreading,Collections,Deadlock,我想知道不同步Java中多个线程修改的集合可能产生的最坏后果是什么(除了数据损坏) 例如,线程的数量可以超过10个,集合(HashSet)可以增长到大约100000个元素(甚至更多) 感谢因为HashSet在内部使用HashMap,所以您只需查看HashMap的putVal方法定义,并亲自查看—在执行该方法的任何时候,另一个线程都可能开始执行相同的操作。例如,它可以在调整大小时捕获数据,这意味着数据可能会写入旧表,或者同时创建两个新表 结果总是数据损坏,在发生此类事件后甚至可能不起作用 由于Ha

我想知道不同步Java中多个线程修改的集合可能产生的最坏后果是什么(除了数据损坏)

例如,线程的数量可以超过10个,集合(HashSet)可以增长到大约100000个元素(甚至更多)


感谢

因为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你不必提及集合不会被正确修改,这是众所周知的。也称为“您的数据已损坏”。还有什么比这更糟糕的呢?