因此,我只能使用一个线程敌对的单例实现,它将Iterator返回给HashSet。我有两个线程--有时--同时访问这个Iterator来加载数据。我叫他们luckyThread和unluckyThread。其中一个(unluckyThread)抛出一个ConcurrentModificationException。
问:假设其他线程都很好,安全吗?具体而言: luckyThread加载的数据是否没有损坏?(发生这种情况的几次-系统运行得很好,除了unluckyThread之外)--不要认为这个问题需要任何代码示例,但是如果需要的话,我很乐意提供它们。
Update:(不详细介绍)只要其中一个线程加载干净的数据集,系统就会正常。不用说,我解决了这个问题,但这让我想要从这样的例外中恢复过来,我在网上没有发现任何具体的东西。
发布于 2015-03-12 20:00:10
如果您查看ConcurrentModificationException的文档,就会清楚地指出:
请注意,通常情况下,不能保证快速失败的行为在不同步并发修改的情况下提供任何硬的保证。快速失败的操作在最大努力的基础上将ConcurrentModificationException抛出。因此,编写一个依赖于此异常的程序是错误的: ConcurrentModificationException应该只用于检测bug。
相反,您可能应该使用一些其他的机制来确保没有并发访问(比如在访问底层的synchronized-block时使用一个单独的HashSet)。
发布于 2015-03-12 20:30:27
引发异常是因为备份存储已更改,这使得该存储上的迭代器的任何使用都容易受到异常的影响。如果编写得不好,甚至可以在单个线程应用程序中发生这种情况。在这种情况下,您的线程都不太幸运,因为当更改发生时,这两个线程都会遭受此异常。
即使没有对基础HashSet进行更改,让两个线程访问迭代器也会导致不确定的行为,因为这两个线程都会改变迭代器的内部状态,更不用说在最好的情况下,每个线程将从您的集合中获取不同的项。
代码本来就不安全,必须重写才能使用threadsafe集,并且不能在线程之间共享迭代器。
发布于 2015-03-12 21:20:02
这绝对不安全。您现在看到的是最好的情况:一个线程获得一个ConcurrentModificationException。可能会比这更糟。在并发访问下未定义HashSet的行为。我不确定HashSet上的迭代器有多稳定,但是快速查看源代码,我就会认为它可能出了很大问题。如果这些键在迭代过程中被重新散列,那么您就有很好的机会在无限循环中结束。
结论:要么同步对迭代器的访问,要么创建集合的副本(在同步块中),要么更改为线程安全集合。
https://stackoverflow.com/questions/29019035
复制相似问题