Scala val必须保护同步的并发访问? [英] Scala val has to be guarded with synchronized for concurrent access?

查看:240
本文介绍了Scala val必须保护同步的并发访问?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如我所读到的,由于各种原因,Scala不可变 val 不会转换为Java final 。这是否意味着从其他线程访问 val 必须保护同步,以保证可见性?

As I read, Scala immutable val doesn't get translated to Java final for various reasons. Does this mean that accessing a val from an other Thread must be guarded with synchronization in order to guarantee visibility?

推荐答案

作为对象成员,一旦初始化, val 不会在对象的生命周期中更改它们的值。因此,如果对象的引用在构造函数中没有转义,则它们的值被保证对所有线程可见。而且,事实上,他们得到如下所示的Java final 修饰符:

As object members, once initialized, vals never change their values during the lifetime of the object. As such, their values are guaranteed to be visible to all threads provided that the reference to the object didn't escape in the constructor. And, in fact, they get Java final modifiers as illustrated below:

object Obj {
  val r = 1

  def foo {
    val a = 1
    def bar = a
    bar
  }
}

使用javap:

...
private final int r;
...

public void foo();
...
   0:   iconst_1
   1:   istore_1
   2:   aload_0
   3:   iload_1
   4:   invokespecial   #31; //Method bar$1:(I)I
   7:   pop
...
private final int bar$1(int);
...
   0:   iload_1
   1:   ireturn
...

作为方法局部变量,它们仅在方法中使用,或者它们被传递给嵌套方法或闭包作为参数(参见 bar $ 1 以上)。一个闭包可能被传递给另一个线程,但它只有一个final字段,其值为local val 。因此,从创建它们到所有其他线程的地方,它们是可见的,并且不需要同步。

As method locals, they are used only within the method, or they're being passed to a nested method or a closure as arguments (see lifted bar$1 above). A closure might be passed on to another thread, but it will only have a final field with the value of the local val. Therefore, they are visible from the point where they are created to all other threads and synchronization is not necessary.

注意,这里没有说明对象 val 指向 - 它本身可以是可变的并且保证同步。

Note that this says nothing about the object the val points to - it itself may be mutable and warrant synchronization.

在大多数情况下,不能通过反射 val 成员声明实际上生成一个具有相同名称的getter和一个私有字段,getter访问。尝试使用反射修改字段将导致 NoSuchFieldException 。你可以修改它的唯一方法是添加一个专门注释到你的类,这将使专业字段受保护,因此可以反射。我目前不能想到任何其他可能改变声明为 val ...

In most cases the above cannot be violated via reflection - the Scala val member declaration actually generates a getter with the same name and a private field which the getter accesses. Trying to use reflection to modify the field will result in the NoSuchFieldException. The only way you could modify it is to add a specialized annotation to your class which will make the specialized fields protected, hence accessible to reflection. I cannot currently think of any other situation that could change something declared as val...

这篇关于Scala val必须保护同步的并发访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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