Reading this site, I've found this:
[The] line
private static final Foo INSTANCE = new Foo();
is only executed when the class is actually used, this takes care of the lazy instantiation, and is it guaranteed to be thread safe.
Why this guaranteed to be thread safe? Because this field is final? Or for some other reason?
Because it's final, yes. Final variables have special thread-safety semantics, in that other threads are guaranteed to see the final field in at least the state it was in when its constructor finished.
This is in JLS 17.5, though the language there is a bit dense. These semantics were introduced in Java 1.5, in particular by JSR-133. See this page for a non-spec discussion of JSR-133 and its various implications.
Note that if you modify the instance after its constructor, that is not necessarily thread safe. In that case, you have to take the usual thread safety precautions to ensure happens-before edges.
I'm fairly sure (though not quite 100%) that the fact that only one thread does the class initialization is not a factor here. It's true that the class is only initialized by one thread, but I don't believe there are any specific happens-before edges established between that thread any any other thread that uses the class (other than that other thread not having to re-initialize the class). So, without the final
keyword, another thread would be able to see a partially-constructed instance of the object. The specific happens-before edges the JMM defines are in JLS 17.4.5, and class initialization is not listed there.
Class constructors and static/instance initializers are guaranteed to be atomically executed and since private static final FOO INSTANCE = new FOO;
is equivalent to
private static final FOO INSTANCE;
static{
INSTANCE = new FOO();
}
this case falls in the above category.
It is guaranteed to be thread safe because the JVM guarantees that static initializers are executed on a single thread.
It doesn't mean that the instance of Foo is internally thread safe- it just means that you are guaranteed that the constructor of Foo will be called exactly once, on one thread, via this particular code path.
The static initialisation block of any class is guaranteed to be single threaded. A simpler singleton is to use an enum
enum Singleton {
INSTANCE;
}
This is also threads safe and the class lazy-initialised.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With