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

上記の例のように、ユーザーはSingletonオブジェクトになり、userCountByAgeMapは遅延して初期化されます。スカラオブジェクトでは、不変のvalスレッドセーフですか?

この初期化原子はですか?即ち、1つのスレッドのみがそれを初期化することができる。
と仮定userCountByAgeMapは、スレッドAにより初期化され、それはB.

をスレッドに表示されます初期化が保証されない原子/メモリ可視でない場合は遅延valがそれを修正するように、変数をuserCountByAgeMap作るだろうか?

答えて

3

Scalaでは、オブジェクトは静的ブロックで初期化されるため、スレッドの安全性はJVMによって保証されます(Java静的初期化子はスレッドセーフです)。アナライザのバイトコードにはJAD decompilerを使用できます。 $の.classファイルユーザー

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

そして、逆コンパイル:ここではコードです

// 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

はい、はobjectでスレッドセーフですが、thread safeの場合はlazy valに変更する必要はありません。 @Artavazd Balayanバイトコードとして、スカラobjectと同じです。のシングルトンオブジェクトです。それに等しいです:私たちはときclass(ユーザー)Javaのstatic blockはinitのだろう知っているように

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

それは、スレッドセーフですので、ロードされます。

lazy valスレッドセーフは解決するためですフィールドは怠惰で、起動時にはinitだけです。しかし、それでもをで初期化すると複数のスレッド間でスレッドセーフなを保持してください。

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

関連する問題