Scala lazy values : performance penalty? Threadsafe? [duplicate]
Asked Answered
D

2

15

Possible Duplicate:
What's the (hidden) cost of lazy val? (Scala)

Scala allows the definition of lazy values

lazy val maybeUnusedValue = someCostlyInitialization

where someCostlyInitialization is evaluated only on the first use of maybeUnusedValue. That is, it is evaluated at most once, and if maybeUnusedValue is never used, it is also never evaluated at all.

Is this threadsafe? What are the performance implications of this? If this is to be threadsafe, it has to use some kind of syncronization / use Java volatile in some way. Unfortunately the Scala language specification says nothing about this.

Dinnerware answered 4/11, 2010 at 9:11 Comment(1)
Copy of #3041753Tosh
B
14

It is made thread-safe using double-checked locking http://code-o-matic.blogspot.com/2009/05/double-checked-locking-idiom-sweet-in.html Obviously this does mean that accessing lazy vals is slower than non-lazy ones.

Barbosa answered 4/11, 2010 at 9:20 Comment(4)
So, basically, this means that accessing a lazy value for the first time is much slower than a direct value (an might even create deadlocks in weird cases), but the subsequent accesses are hardly slower than non-lazy values. It seems this is not to be taken lightly, only for really expensive initializations.Naumann
@hstoerr In what case would this create deadlock? The double-checked locking seems to properly synchronize this.Boutonniere
@Cristian Vrabie: I think Scala only required Java 1.4 at the time, didn't it? And DCL is broken in Java 1.4.Barbosa
@Alexey Romanov: Ah, I forgot about that. It's been too long since I had a contact with Java 1.4. Thanks for clarifying this.Boutonniere
E
7

UPDATE: OOPS, as Vasil pointed out, the question is a copy of another thread, and as it happens, so is this answer.

I took this class:

class Foo {
  lazy val test = "hi"
}

Compiled and decompiled (with 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;
    }
  }
}

As you can see it is using the double check paradigm with a volatile variable. So I think it is safe

Elwood answered 4/11, 2010 at 9:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.