Java Scala中的不变性和线程安全性
我正在读这本书,当我读到不变性和线程安全性之间的关系时,我试图深入了解。因此,我发现至少有一个用例,在Java中构造一个不可变的类可以导致发布一个未正确构造的对象 根据link,如果类的字段没有被分离Java Scala中的不变性和线程安全性,java,scala,thread-safety,immutability,Java,Scala,Thread Safety,Immutability,我正在读这本书,当我读到不变性和线程安全性之间的关系时,我试图深入了解。因此,我发现至少有一个用例,在Java中构造一个不可变的类可以导致发布一个未正确构造的对象 根据link,如果类的字段没有被分离final,编译器可以重新排序需要执行的语句,以便构造对象。事实上,根据link,要构建对象,JVM需要执行以下非原子操作: 分配一些内存 创建新对象 使用其默认值初始化其字段(布尔值为false,其他原语为0,对象为null) 运行构造函数,其中也包括运行父构造函数 将引用指定给新构造的对象 我的
final
,编译器可以重新排序需要执行的语句,以便构造对象。事实上,根据link,要构建对象,JVM需要执行以下非原子操作:
case class
es线程安全wrt是否就是上述构造问题
感谢大家。我在Stackoverflow和互联网上进行了深入搜索。关于我提出的问题,没有太多的信息。我发现这个问题,所以有一个有趣的答案: 正如@retronym所建议的,我使用了
javap-pa.class
来解构一个.class
文件,该文件包含一个案例类
,并由scalac
编译。我发现这个班
case class A(val a: Any)
由scala编译器编译成相应的Java类,该类将其唯一属性a
声明为final
Compiled from "A.scala"
public class A implements scala.Product,scala.Serializable {
// Final attribute
private final java.lang.Object a;
public static <A extends java/lang/Object> scala.Function1<java.lang.Object, A
> andThen(scala.Function1<A, A>);
public static <A extends java/lang/Object> scala.Function1<A, A> compose(scala
.Function1<A, java.lang.Object>);
public java.lang.Object a();
public A copy(java.lang.Object);
public java.lang.Object copy$default$1();
public java.lang.String productPrefix();
public int productArity();
public java.lang.Object productElement(int);
public scala.collection.Iterator<java.lang.Object> productIterator();
public boolean canEqual(java.lang.Object);
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public A(java.lang.Object);
}
转换为具有final
属性的Java类
总之,我认为我们可以说,一个只有
val
属性的Scala类被转换成一个只有final
属性的对应Java类。由于JVM的JMM,这个Scala类在构建过程中应该是线程安全的。也可以将其作为一个答案发布?@SteveWaldman,你能总结一下你给出的问题的答案吗?我试着读了一遍,但是信息太多了,而且重点与我的问题不完全相同。非常感谢。没有人接受答案。一张海报为Scala的核心不可变表是线程安全的这一说法进行了长时间的论证,只要您从Scala.\u
包之外访问它们,但我认为这个答案最终没有说服力。我认为线程安全问题在实践中不太可能,例如列表和向量,但我认为Java内存模型足够灵活,如果不同步访问,就无法保证安全性。我觉得这非常令人失望,但到目前为止,还没有人向我提出有说服力的理由来保证安全。请看@axel22的评论。对不起@DanielL.,你是什么意思?
class A1(val a: Any)