Created
January 24, 2012 17:40
-
-
Save ms-tg/1671423 to your computer and use it in GitHub Desktop.
Scala 'lazy val' vs Java memoization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Without worrying about concurrency, we can simply cache the return value, | |
* using null to indicate that it has not yet been calculated... | |
*/ | |
public class Memoize1 extends Original { | |
private Integer total; | |
@Override | |
public int total() { | |
if (total == null) { | |
total = super.total(); | |
} | |
return total; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Makes this safe for concurrency -- all calls synchronized -- but this | |
* is unnecessarily slow if calling frequently... | |
*/ | |
public class Memoize2 extends Original { | |
private Integer total; | |
@Override | |
public int total() { | |
synchronized(this) { | |
if (total == null) { | |
total = super.total(); | |
} | |
} | |
return total; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* The so called "double check" pattern: | |
* safe for concurrency, and fast | |
*/ | |
public class Memoize3 extends Original { | |
private Integer total; | |
@Override | |
public int total() { | |
if (total == null) { | |
synchronized(this) { | |
if (total == null) { | |
total = super.total(); | |
} | |
} | |
} | |
return total; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Say we have a method which always returns the same calculation... | |
*/ | |
public class Original { | |
public int total() { | |
return 1+1; // potentially expensive calculation here | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* So what does Scala generate for this? | |
*/ | |
class ScalaLazy { | |
lazy val total = 1+1 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Approximate decompilation of Scala lazy val, | |
* see http://code-o-matic.blogspot.com/2009/05/double-checked-locking-idiom-sweet-in.html | |
*/ | |
public class ScalaLazy { | |
public volatile int bitmap$0; | |
private int total; | |
public int total() { | |
if ((bitmap$0 & 1) == 0) { | |
synchronized(this) { | |
if ((bitmap$0 & 1) == 0) { | |
total = 1+1; // here's the expensive calculation | |
bitmap$0 = bitmap$0 | 1; | |
} | |
} | |
} | |
return total; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
your 'memoize3.java' isn't fully threadsafe unless the
total
field is declaredvolatile
.