Immutability and thread-safety in Scala

2019-05-08 14:28发布

I'm reading the book Java concurrency in practice and when I read about the relation between immutability and thread-safety I tried to get deeper. So, I discovered that there is at least a use case in which the construction of an immutable class in Java can lead to the publishing of a non properly constructed object.

According to 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, to build an object the JVM needs to do these non-atomic operations:

  1. allocate some memory
  2. create the new object
  3. initialise its fields with their default value (false for boolean, 0 for other primitives, null for objects)
  4. run the constructor, which includes running parent constructors too
  5. assign the reference to the newly constructed object

My question is: what about Scala? I know that Scala is based on the concurrency model of Java, so it is based on the same Java Memory Model. For example, are case classes thread-safe wrt the above construction problem?

Thanks to all.

1条回答
祖国的老花朵
2楼-- · 2019-05-08 15:28

I've made some deep search on Stackoverflow and on the Internet. There is not so much information about the question I've made. I found this question on SO that has an interesting answer: Scala final vs val for concurrency visibility.

As proposed by @retronym I've used javap -p A.class to destructure a .class file containing a case class and compiled by scalac. I found that the class

case class A(val a: Any)

is compiled by the scala compiler into a corresponding Java class that declares its unique attribute a as 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);
}

As we know, a case class in Scala generates automatically a bunch of utilities for us. But also a simple class like this

class A1(val a: Any)

is translated into a Java class that has a final attribute.

Summarizing, I think we can say that a Scala class that has only val attributes is translated into a corresponding Java class that has final attributes only. Due to the JMM of the JVM, this Scala class should be thread-safe during the construction process.

查看更多
登录 后发表回答