Let's suppose I have a shared object like this:
class Shared {
private Value val;
//synchronized set
public synchronized void setValue(Value val) {
if (this.val == null) {
this.val = val;
} else {
throw new IllegalStateException();
}
}
//unsynchronized get
public Value getValue() {
return this.val;
}
}
If I have a single thread set the value during app initialization, before any other thread has a chance to read it, and nothing ever changes the value again, is it safe to read the value unsynchronized, or do I run the risk of other threads never seeing the set value (because the variable isn't volatile
and not guaranteed to be flushed to the main memory)?
Imagine this in the context of a web application where the setting occurs during Servlet initialization. I do not know whether other threads have been created or not at this point, as this is the container's job. But I presume a thread pull that will handle future requests will have been created by then.
If unsafe, is there a way I'm missing to safely initialize the value without paying a price on every read forever even though the value will never change? I.e. is there a way to flush the value once only?
Also, isn't this exactly what e.g. Spring does all the time? While the container is being initialized, all kinds of unsynchronized setting on singletons is happening: beans getting injected via setters, @PostConstruct
initializers firing etc. Once it is done, requests are being accepted and no modifications take place. If this was unsafe, wouldn't every singleton method ever need to be synchronized?