HashSet 和多线程

HashSet and multithreading

我在 Java 7.

上工作

我想知道方法 contains 在 HashSet 对象上是否是线程安全的。

HashSet 由一个线程初始化。然后我们用不可修改的集合 (Collections.unmodifiableSet) 包装 HashSet。初始化后,多个线程只调用方法contains.

当我阅读 Java文档时,我不清楚。

HashSet Javadoc 我们可以阅读

This class implements the Set interface, backed by a hash table (actually a HashMap instance).

...

Note that this implementation is not synchronized.

而在 HashMap Javadoc 上,我们可以阅读:

Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.)

对我来说,这意味着方法 contains 不是结构修改。

那么多次调用方法contains是线程安全的吗?

如果是这样:是否保证所有 JVM 实现(如 IBM JVM)?

一般来说,不可能只在读取操作之间存在并发竞争(因此也不会发生冲突)。读写操作之间会出现并发问题。因此,交错的多个读取操作总是 thread-safe(如果我们假设 thread-safety 的概念定义明确)。

现在,还有一种情况可能存在并发问题,这是在数据结构初始化期间,因为在您的情况下,这可以被认为是唯一的修改(写操作)。为了确保所有后续 contains() 调用都将看到完全初始化的 Set,您必须确保它已正确初始化。这个概念在 Java 中被定义为 "safe-publication",您可以阅读 here or in the book "Java Concurrency in Practice" 书中的更多内容。

总而言之,Collections.unmodifiableSet() 通过 final 字段以安全的方式发布结果。 所以,是的,你可以确定所有 contains() 都会看到完全初始化的 Set