早在2008年,Stackoverflow上就有manyquestions询问不可修改的集合是否是线程安全的,但JDK 10(2018年发布)引入了一个不同的野兽:现有集合中不可修改的copies个.

List.copyOf()个州:

如果给定的集合随后被修改,则返回的列表将不会反映这些修改.

这是否意味着返回值List.copyOf()Set.copyOf()Map.copyOf()都是线程安全的?

(我意识到,集合中包含的元素本身不能保证是线程安全的.)

推荐答案

由于通过例如List.of(…)List.copyOf(…)创建的集合不反映对指定数组或集合的后续更改,并且通常是不可变的,因此不可能在构造后执行修改,并且在没有并发修改的情况下,不可能存在任何线程安全问题.

剩下的问题是,这些藏品的建设本身是否不受不安全出版的影响.通常,您应该使用适当的 struct 将对象发布到其他线程,而不是依赖不安全的发布.

但回想一下,Unmodifiable Lists人说

  • 他们都是unmodifiable岁.不能添加、删除或替换元素.调用列表上的任何赋值函数方法都会导致抛出UnsupportedOperationException.但是,如果包含的元素本身是可变的,这可能会导致列表的内容似乎发生变化.

沿着value-based的链接,我们发现:

基于值的类

有些类(如java.lang.Integerjava.time.LocalDate)是基于值的.基于值的类具有以下属性:

  • 该类仅声明最终实例字段(尽管这些字段可能包含对可变对象的引用);

对于不受不安全发布影响的不可变对象,最终字段非常重要.AS JLS§17.5. final Field Semantics指定:

final字段还允许程序员在没有同步的情况下实现线程安全的不可变对象.线程安全的不可变对象被所有线程视为不可变,即使使用数据争用来在线程之间传递对不可变对象的引用.这可以提供安全保证,防止不正确或恶意代码误用不可变的类.

但我们仍然必须假设JDK开发人员的意图是"实现线程安全的不可变对象",而不是通过显式使用final个字段来让开发人员感到惊讶,然后故意 destruct 安全保证.

如果有疑问,请使用安全出版物.不会疼的.

即使您已经说过这一点,但需要强调的是,如果所包含的元素是可变的,则这并不适用于它们.

Java相关问答推荐

了解Android Studio中的调试器输出

无法在org. openjfx:javafx—fxml:21的下列变体之间进行 Select

根据对象和值的参数将映射<;T、值&>转换为列表<;T&>

安装Java Jar应用程序的Install4j遇到ClassNotFoundException的运行时错误

对字符串长度进行排序,但颠倒了顺序(最长字符串在前)

S,要对Java复制构造函数深度克隆所有属性进行单元测试,最可靠的方法是什么?

使用用户引入的参数生成人员数组

将PNG转换为位图自定义十六进制字符串

Domino中不同的java.Protocol.handler.pkgs设置在XPages Java中导致错误

如何在Struts2中使用操作类中的结果注释重定向到不同的命名空间

当我将JTextField的getText函数与相等的String进行比较时;t返回true

如何使用带有可选参数的类生成器?

java21预览未命名的符号用于try-with-resources

使用Java线程进行并行编程

放置在变量中的Java成员引用不相等

将天数添加到ZonedDateTime不会更改时间

ANTLR 接受特殊字符,例如 .标识符或表达式中的(点)和 ,(逗号)

如何在 BlueJ 中自动关闭控制台

Hibernate try 在 CrudRepository 中插入 null id

防止屏幕转换后重叠?