gpt4 book ai didi

Scala final 与 val 的并发可见性

转载 作者:行者123 更新时间:2023-12-03 09:49:55 25 4
gpt4 key购买 nike

在 Java 中,当跨多个线程(以及一般情况下)使用对象时,将字段设为 final 是一种很好的做法。例如,

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

在这种情况下,obj 的可见性将在多个线程中保持一致(假设 obj 也具有所有 final 字段),因为它是使用 final 关键字安全构造的。

在 scala 中, val 似乎不会编译为最终引用,而是 val 是 scala 中的语义,可防止您重新分配变量( Scala final variables in constructor )。如果 scala 构造函数变量未定义为 final,它们是否会遇到同样的问题(在 actor 中使用这些对象时)?

最佳答案

另一个问题的答案具有误导性。术语 final 有两种含义:a) 对于 Scala 字段/方法和 Java 方法,它意味着“不能在子类中被覆盖”和 b) 对于 Java 字段和 JVM 字节码,它意味着“该字段必须在构造函数中初始化并且不能重新分配”。

val 标记的类参数(或者,等效地,没有修饰符的案例类参数)在第二种意义上确实是最终的,因此是线程安全的。

这里有证据:

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 运行:
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 与 val 的并发可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7626611/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com