Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.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_Linux_Multithreading_Java 8 - Fatal编程技术网

Java 从并发修改异常中恢复

Java 从并发修改异常中恢复,java,linux,multithreading,java-8,Java,Linux,Multithreading,Java 8,因此,我一直使用一个线程敌对的单例实现,它将迭代器返回到哈希集。 我有两个线程——有时——同时访问这个迭代器来加载数据。我会称他们为幸运线程和不幸线程。 其中一个(unluckyThread)抛出ConcurrentModificationException 问题:可以安全地假设其他线程一切正常吗? 具体来说:luckyThread加载的数据是否没有损坏? (这两次发生时,系统运行得很好,除了不顺利的线程) 我不认为这个问题需要任何代码示例,但如果需要,我很乐意提供它们 更新:(不涉及细节)只要

因此,我一直使用一个线程敌对的单例实现,它将迭代器返回到哈希集。 我有两个线程——有时——同时访问这个迭代器来加载数据。我会称他们为幸运线程和不幸线程。 其中一个(unluckyThread)抛出ConcurrentModificationException

问题:可以安全地假设其他线程一切正常吗? 具体来说:luckyThread加载的数据是否没有损坏? (这两次发生时,系统运行得很好,除了不顺利的线程) 我不认为这个问题需要任何代码示例,但如果需要,我很乐意提供它们


更新:(不涉及细节)只要其中一个线程加载一个干净的数据集,系统就正常。不用说,我已经解决了这个问题,但这让我开始考虑从这些异常中恢复,我在网上没有找到任何具体的信息。

如果您查看的文档,它清楚地表明:

请注意,通常不能保证快速失效行为 说起来,在有人在场的情况下,不可能做出任何硬性保证 未同步的并发修改。快速失败操作抛出 ConcurrentModificationException尽最大努力。因此, 编写依赖此异常的程序是错误的 其正确性:ConcurrentModificationException仅应使用 检测错误


相反,您可能应该使用一些其他机制来确保没有并发访问(例如在访问底层HashSet时使用与singleton同步的
块)。

另一种方法是使用HashMap代替。在多线程应用程序中访问ConcurrentHashMap时,不需要同步块。

引发异常是因为备份存储已更改,这使得在该存储上使用迭代器容易受到异常的攻击。如果编写得不好,这甚至可能发生在单线程应用程序中。在您的情况下,您的两个线程都不是非常幸运,因为当发生更改时,两个线程都可能出现这种异常

即使不更改基础哈希集,让两个线程访问迭代器也会导致不确定的行为,因为这两个线程都会更改迭代器的内部状态,更不用说在最佳情况下,每个线程将从迭代器集中获取不同的项


代码不安全,必须重写才能使用线程安全集,并且不能在线程之间共享迭代器。

这绝对不安全。您现在看到的是最佳情况:一个线程获得一个
ConcurrentModificationException
。情况可能比这更糟。在并发访问下,
HashSet
的行为未定义。我不确定
HashSet
上的迭代器有多稳定,但快速查看源代码让我觉得它可能会出错。如果在迭代过程中对关键点进行了重新灰化,则很有可能最终进入无限循环


结论:要么同步对迭代器的访问,要么创建集合的副本(在同步块中),要么更改为线程安全的集合。

不,假设是不安全的,你永远不知道哪个线程是幸运的,哪个线程是不幸运的,最好选择同步化访问。你不能解决这个问题吗?你仍然不能在线程之间共享迭代器。多个线程获得自己的迭代器并使用它们是安全的,但不能共享。@Robin:同意。在这种情况下,这是不够的。这并不能解决多线程访问返回迭代器的问题。那段代码只需要重构就可以不这样做。@Robin:很公平,我可能应该说“在访问底层哈希集时使用单例的同步块”。。。至少在HashSet的情况下,它实际上会在每次iterator()调用时返回一个新的迭代器,因此线程不会共享同一个迭代器,但当然,如果其中任何一个或其他东西会导致基础集合发生更改,则并发使用它们仍然是不安全的。“可能是安全的”是不正确的。最坏的情况是,如果基础集合发生更改,则迭代中会出现无限循环。你可能会很幸运,但绝对不安全。@Guillaume:是的,我删除了第一句话