Reputation: 85
object Users {
val userCountByAgeMap = readFromFile(); // read from file returns immutable map
}
As in above example in scala, Users will be Singleton object and userCountByAgeMap will be initialized lazily.
So is this initialization atomic? i.e. one and only one thread will be able to initialize it.
Suppose userCountByAgeMap is initialized by Thread A, will it be visible to Thread B.
If initialization is not atomic/memory visibility not ensured, will making userCountByAgeMap variable as lazy val fix it?
Upvotes: 6
Views: 1259
Reputation: 14217
Yes, val
is thread safe in object
, you don't need to change it to lazy val
for thread safe
. As @Artavazd Balayan bytecode, the Scala object
is equal to Java's singleton object. so it's equal to:
class Users {
public static Users users;
static {
users = new Users();
}
val userCountByAgeMap = readFromFile(); // read from file returns immutable map
}
As we know Java's static block will init when class
(Users) is loaded, so it's thread safe.
And need to call out, the lazy val
thread safe is for solving field is lazy, and only init when it invoke. but still keep it's thread safe between multiple threads when init by Double checking locking.
http://docs.scala-lang.org/sips/pending/improved-lazy-val-initialization.html
Upvotes: 2
Reputation: 2413
In Scala, an object is initialized in a static block so thread safety is guaranteed by JVM (Java static initializers are thread safe). You can use JAD decompiler to analyzer bytecode. Here is the code:
object Users {
val userCountByAgeMap = Map.empty[String, Int]
}
And decompiled Users$.class file:
// 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$();
}
}
As you're using immutable Map which automatically gives you thread safety. So it's ok to access this field from different threads.
Upvotes: 4