Scala 中的不变性和线程安全
Immutability and thread-safety in Scala
我正在读 Java concurrency in practice 这本书,当我读到 不变性 和 线程安全 之间的关系时,我试图变得更深。因此,我发现至少有一个用例,其中在 Java 中构造不可变的 class 会导致发布未正确构造的对象。
根据 this link, if the fields of the class are not declated final
, the compiler could reorder the statements that needs to be done in order to construct the object. In fact, according to this link,要构建对象,JVM 需要执行这些非原子操作:
- 分配一些内存
- 创建新对象
- 使用默认值初始化它的字段(布尔值为 false,其他基元为 0,对象为 null)
- 运行 构造函数,其中也包括 运行ning 父构造函数
- 将引用分配给新构造的对象
我的问题是:Scala 怎么样?我知道Scala是基于Java的并发模型,所以也是基于同样的Java内存模型。例如,case class
对于上述构造问题是否是线程安全的?
感谢大家。
我在 Whosebug 和 Internet 上进行了一些深入的搜索。关于我提出的问题,没有太多信息。我在 SO 上发现这个问题有一个有趣的答案:Scala final vs val for concurrency visibility.
正如@retronym 所建议的那样,我使用 javap -p A.class
解构了一个包含 case class
并由 scalac
编译的 .class
文件。我发现 class
case class A(val a: Any)
由 scala 编译器编译成相应的 Java class 声明其唯一属性 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();
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);
}
正如我们所知,Scala 中的 case class
会自动为我们生成一堆实用程序。还有一个简单的class像这样
class A1(val a: Any)
被翻译成具有 final
属性的 Java class。
总结一下,我想我们可以说只有 val
属性的 Scala class 被翻译成对应的 Java class 有 final
仅限属性。由于JVM的JMM,这个Scalaclass在构建过程中应该线程安全
我正在读 Java concurrency in practice 这本书,当我读到 不变性 和 线程安全 之间的关系时,我试图变得更深。因此,我发现至少有一个用例,其中在 Java 中构造不可变的 class 会导致发布未正确构造的对象。
根据 this link, if the fields of the class are not declated final
, the compiler could reorder the statements that needs to be done in order to construct the object. In fact, according to this link,要构建对象,JVM 需要执行这些非原子操作:
- 分配一些内存
- 创建新对象
- 使用默认值初始化它的字段(布尔值为 false,其他基元为 0,对象为 null)
- 运行 构造函数,其中也包括 运行ning 父构造函数
- 将引用分配给新构造的对象
我的问题是:Scala 怎么样?我知道Scala是基于Java的并发模型,所以也是基于同样的Java内存模型。例如,case class
对于上述构造问题是否是线程安全的?
感谢大家。
我在 Whosebug 和 Internet 上进行了一些深入的搜索。关于我提出的问题,没有太多信息。我在 SO 上发现这个问题有一个有趣的答案:Scala final vs val for concurrency visibility.
正如@retronym 所建议的那样,我使用 javap -p A.class
解构了一个包含 case class
并由 scalac
编译的 .class
文件。我发现 class
case class A(val a: Any)
由 scala 编译器编译成相应的 Java class 声明其唯一属性 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();
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);
}
正如我们所知,Scala 中的 case class
会自动为我们生成一堆实用程序。还有一个简单的class像这样
class A1(val a: Any)
被翻译成具有 final
属性的 Java class。
总结一下,我想我们可以说只有 val
属性的 Scala class 被翻译成对应的 Java class 有 final
仅限属性。由于JVM的JMM,这个Scalaclass在构建过程中应该线程安全