2010-11-04 67 views
13

可能重複:
What's the (hidden) cost of lazy val? (Scala)斯卡拉懶惰值:表現懲罰?線程?

Scala的允許其中someCostlyInitialization僅在第一次使用的maybeUnusedValue評價懶惰值

lazy val maybeUnusedValue = someCostlyInitialization 

的定義。也就是說,最多隻會評估一次,如果從未使用maybeUnusedValue,它也根本不會評估。

這是線程安全嗎?這有什麼性能影響? 如果這是線程安全的,它必須以某種方式使用某種同步/使用Java volatile。不幸的是,Scala language specification沒有提到這一點。

+1

副本http://stackoverflow.com/questions/3041253/whats-the-hidden-cost-of-lazy-val-scala – 2010-11-04 09:19:41

回答

12

這是使用雙重檢查鎖定線程安全http://code-o-matic.blogspot.com/2009/05/double-checked-locking-idiom-sweet-in.html很明顯,這意味着訪問懶惰vals比非懶惰的慢。

+1

所以,基本上,這意味着第一次訪問懶惰值是多比直接值慢(甚至可能在奇怪的情況下產生死鎖),但後續訪問不會慢於非惰性值。看起來這不是輕率的,只是用於真正昂貴的初始化。 – 2010-11-04 09:34:20

+0

是的,沒錯。 – 2010-11-04 11:12:27

+0

@hstoerr在什麼情況下會造成死鎖?雙重檢查鎖定似乎正確地同步這一點。 – 2011-10-17 10:24:03

7

更新:OOPS,正如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; 
    } 
    } 
} 

正如你可以看到它使用了雙重檢查模式與volatile變量。所以我認爲它是安全的