【问题标题】:Effects of concurrent accesses on a HashSet并发访问对 HashSet 的影响
【发布时间】:2013-02-04 11:04:19
【问题描述】:

我遇到了一些阴暗的代码,其中 HashSet 被多个线程同时访问和修改,我想知道这可能会产生什么影响,考虑到 Javadoc 只解释了这种行为是“非确定性”在并发、非同步访问下。

具体来说,对remove(element) 的调用是否有可能返回true,但调用的效果永远不会被其他线程看到(即contains(element) 在其他线程中总是会返回true) ?

PS:只是为了让你放心,我知道这段代码很糟糕,我会将HashSet 替换为等效的同步集合。

【问题讨论】:

    标签: java collections synchronization hashset


    【解决方案1】:

    多线程访问HashSet即可。

    • 导致您所做的更改不被其他线程看到。
    • 迭代器因 ConcurrentModifcationException 而失败。
    • 在 HashSet 代码中进入无限循环的线程(很少见,但确实很糟糕)

    注意:一个简单的替换是使用

    Set<Type> set = Collections.newSetFromMap(new ConcurrentHashMap<Type, Boolean>());
    

    【讨论】:

    • 感谢您的回答@Peter!你能帮我澄清一下吗?当您说“另一个线程没有看到更改”时,是否假设最终会看到更改,或者是否有可能无限期地丢弃一个(或多个)线程的更改效果?
    • 根据经验,我通常认为并发之神讨厌我们,并且可能发生最坏的事情
    • @ahelix 根本无法保证。结果肯定不会被丢弃,但知名度可能会被无限期推迟。更糟糕的是,各种单独的修改可能会在不同的时间变得可见,从而导致 HashSet 对象完全损坏。
    • @ahelix 除非您有一个编写器和多个读取器(在这种情况下,它应该最终保持一致),否则更改很可能永远丢失。如果您有多个编写器,则无法相互破坏更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-18
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 2016-08-29
    • 1970-01-01
    相关资源
    最近更新 更多