Scala的惰性值:会有性能损失吗?线程安全吗?

15

可能是重复问题:
什么是lazy val的(隐藏)成本? (Scala)

Scala允许定义lazy值

lazy val maybeUnusedValue = someCostlyInitialization

其中someCostlyInitialization仅在第一次使用maybeUnusedValue时进行评估。也就是说,它最多只会被评估一次,如果maybeUnusedValue从未被使用,则根本不会进行评估。

这是否安全用于多线程?这对性能有何影响? 为了使其线程安全,必须使用某种同步方法/以某种方式使用Java volatile。不幸的是,Scala语言规范对此没有任何说明。


1
延迟求值带来的隐藏成本是什么? - Vasil Remeniuk
2个回答

13

1
基本上,这意味着第一次访问惰性值比直接值要慢得多(在奇怪的情况下甚至可能会创建死锁),但是后续访问几乎与非惰性值一样快。看起来这不应该轻视,只适用于真正昂贵的初始化。 - Hans-Peter Störr
在什么情况下会出现死锁?双重检查锁定似乎可以正确地同步此操作。 - Cristian Vrabie
@Cristian Vrabie:我记得当时Scala只需要Java 1.4,是吗?而且在Java 1.4中DCL是有问题的。 - Alexey Romanov
@Alexey Romanov:啊,我忘记了。自从我上次接触Java 1.4以来已经太久了。感谢您澄清这一点。 - Cristian Vrabie

7

更新:糟糕,正如Vasil指出的那样,这个问题是另一个主题的复制,而且这个答案也是如此。

我上过这门课:

class Foo {
  lazy val test = "hi"
}

编译和反编译(使用jd-gui):

public class Foo
  implements ScalaObject
{
  private String test;
  public volatile int bitmap$0;

  public String test()
  {
    if (
      (this.bitmap$0 & 0x1) == 0);
    synchronized (this)
    {
      if (
        (this.bitmap$0 & 0x1) == 0) {
        this.test = "hi"; this.bitmap$0 |= 1; } return this.test;
    }
  }
}

正如您所看到的,它使用了双重检查范式和易失变量。因此,我认为它是安全的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接