2017-10-11 136 views
3
object Users { 
    val userCountByAgeMap = readFromFile(); // read from file returns immutable map 
} 

正如在上面的scala示例中,用戶將是Singleton對象並且userCountByAgeMap將被懶惰地初始化。在scala對象中,是不可變的val線程安全嗎?

那麼這個初始化是原子嗎?即一個且只有一個線程將能夠初始化它。
假設userCountByAgeMap由線程A初始化,這將是可見的主題B.

如果初始化是不是不能保證原子/內存的知名度,將使得userCountByAgeMap變懶VAL解決這個問題?

回答

3

在Scala中,一個對象在一個靜態塊中初始化,所以JVM保證線程安全(Java靜態初始化器是線程安全的)。您可以使用JAD decompiler來分析器字節碼。下面是代碼:

object Users { 
    val userCountByAgeMap = Map.empty[String, Int] 
} 

和反編譯的用戶$ .class文件:

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. 
// Jad home page: http://www.kpdus.com/jad.html 
// Decompiler options: packimports(3) 
// Source File Name: Users.scala 

import scala.Predef$; 
import scala.collection.immutable.Map; 
import scala.collection.immutable.Map$; 

public final class Users$ 
{ 

    public Map userCountByAgeMap() 
    { 
     return userCountByAgeMap; 
    } 

    private Users$() 
    { 
     userCountByAgeMap = Predef$.MODULE$.Map().empty(); 
    } 

    public static final Users$ MODULE$ = this; 
    private final Map userCountByAgeMap; 

    static 
    { 
     new Users$(); 
    } 
} 

當你使用一成不變的地圖會自動給你線程安全。所以可以從不同的線程訪問這個字段。

1

是的,valobject中是線程安全的,您不需要將其更改爲thread safelazy val。作爲@Artavazd Balayan字節碼,Scalaobject等於Java的單身對象。所以它等於:

class Users { 
    public static Users users; 
    static { 
     users = new Users(); 
    } 
    val userCountByAgeMap = readFromFile(); // read from file returns immutable map 
} 

正如我們知道什麼時候class(用戶)加載的Javastatic block將初始化,所以這是線程安全的。

而且需要調出,lazy val線程安全是爲了解決字段是懶惰的,只有在init調用的時候纔是。但仍然保持線程安全之間的多個線程時,初始化由Double checking locking

http://docs.scala-lang.org/sips/pending/improved-lazy-val-initialization.html

相關問題