I have a hunch that using the holder idiom without declaring the holder field as final is not thread safe (due to the way immutability works in Java). Can somebody confirm this (hopefully with some sources)?
public class Something {
private long answer = 1;
private Something() {
answer += 10;
answer += 10;
}
public int getAnswer() {
return answer;
}
private static class LazyHolder {
// notice no final
private static Something INSTANCE = new Something();
}
public static Something getInstance() {
return LazyHolder.INSTANCE;
}
}
EDIT: I definitely want sourced statements, not just assertions like "it works" -- please explain/prove it's safe
EDIT2: A little modification to make my point more clear - can I be sure that the getAnswer() method will return 21 regardless of calling thread?
The class initialization procedure guarantees that if a static field's value is set using a static initializer (i.e. static variable = someValue;
) that value is visible to all threads:
10 - If the execution of the initializers completes normally, then acquire LC, label the Class object for C as fully initialized, notify all waiting threads, release LC, and complete this procedure normally.
Regarding your edit, let's imagine a situation with two threads T1 and T2, executing in that order from a wall clock's perspective:
Something s = Something.getInstance();
Something s = Something.getInstance(); i = s.getAnswer();
Then you have:
Something INSTANCE = new Something();
, which initialises answer
, T1 release LCINSTANCE
then reads answer
.So you can see that you have a proper happens-before relationship between the write and the read to answer
, thanks to the LC
lock.
It is thread-safe for sure, but is mutable. So anyone who gets it may assign it to something else. And that is first thing to worry about (even before considering thread-safety).
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