我在Java 7上工作。
我想知道方法contains
是否在HashSet对象上是线程安全的。
HashSet由一个线程初始化。然后我们用不可修改的集合(Collections.unmodifiableSet
)包装HashSet。初始化后,多个线程只调用方法contains
。
当我阅读Javadoc时,对我来说还不清楚。
在HashSet Javadoc我们可以阅读
此类实现Set接口,由哈希表(实际上是HashMap实例)支持。
...
请注意,此实施未同步。
在HashMap Javadoc上,我们可以阅读:
请注意,此实现未同步。如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)
对我来说,这意味着方法contains
不是结构修改。
因此对方法contains
的多次调用是否是线程安全的?
如果它是真的:JVM的所有实现(如IBM JVM)都能保证吗?
答案 0 :(得分:4)
通常,在读取操作之间不会出现并发竞争(因而冲突)。读写操作之间出现并发问题。因此,交错的多个读取操作始终是线程安全的(如果我们假设这样一个线程安全的概念已经明确定义)。
现在,还有一种情况可能存在并发问题,这是在数据结构初始化期间,因为在您的情况下,这可以被认为是唯一的修改(写操作)。为了确保所有后续的contains()
调用都能看到完全初始化的Set,您必须确保它已正确初始化。这个概念在Java中定义为“安全发布”,你可以阅读更多关于它here或书籍"Java Concurrency in Practice"的书。
总而言之,Collections.unmodifiableSet()
通过final
字段以安全的方式发布结果。 所以,是的,您确定所有contains()
都会看到完全初始化Set