Scala final vs val用于并发可见性 [英] Scala final vs val for concurrency visibility

查看:195
本文介绍了Scala final vs val用于并发可见性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,当跨多个线程(一般来说)使用对象时,最好将字段设置为final。例如,

In Java, when using an object across multiple threads (and in general), it is good practice to make fields final. For example,

public class ShareMe {
    private final MyObject obj;
    public ShareMe(MyObject obj) {
        this.obj = obj;
    }
}

在这种情况下,obj的可见性将是一致的

In this case, the visibility of obj will be consistent across multiple threads (let's assume obj has all final fields as well) since it is safely constructed using the final keyword.

在scala中,它不会出现val编译下来,因为它是使用final关键字安全构造的。到最后的引用,而是val是scala中的语义,阻止您重新分配变量( Scala final构造函数中的变量)。如果scala构造函数变量没有定义为final,它们会遭受同样的问题(当在actor中使用这些对象时)?

In scala, it doesn't appear val compiles down to a final reference, but rather val is semantics in scala that prevents you from reassigning a variable (Scala final variables in constructor). If scala constructor variables are not defined as final, will they suffer from the same problem (when using these objects in actors)?

推荐答案

另一个问题的答案是误导。 final 有两个含义:a)对于Scala字段/方法和Java方法,意味着不能在子类中重写,b)对于Java字段和JVM字节码意味着该字段必须在构造函数中初始化,不能重新赋值。

The answer to the other question is misleading. There are two meanings of the term final: a) for Scala fields/methods and Java methods it means "cannot be overridden in a subclass" and b) for Java fields and in JVM bytecode it means "the field must be initialized in the constructor and cannot be reassigned".

标记为 val的类参数

Class parameters marked with val (or, equivalently, case class parameters without a modifier) are indeed final in second sense, and hence thread safe.

这是证明:

scala>  class A(val a: Any); class B(final val b: Any); class C(var c: Any)
defined class A
defined class B
defined class C

scala> import java.lang.reflect._
import java.lang.reflect._

scala> def isFinal(cls: Class[_], fieldName: String) = {
     |   val f = cls.getDeclaredFields.find(_.getName == fieldName).get
     |   val mods = f.getModifiers
     |   Modifier.isFinal(mods)
     | }
isFinal: (cls: Class[_], fieldName: String)Boolean

scala> isFinal(classOf[A], "a")
res32: Boolean = true

scala> isFinal(classOf[B], "b")
res33: Boolean = true

scala> isFinal(classOf[C], "c")
res34: Boolean = false

javap ,可以方便地从REPL运行:

Or with javap, which can be conveniently run from the REPL:

scala> class A(val a: Any)
defined class A

scala> :javap -private A
Compiled from "<console>"
public class A extends java.lang.Object implements scala.ScalaObject{
    private final java.lang.Object a;
    public java.lang.Object a();
    public A(java.lang.Object);
}

这篇关于Scala final vs val用于并发可见性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆