2017-10-11 135 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

相关问题