As Evgeniy has stated, the initialization of an application context happens in a single thread. Therefore the answer to your question isn't so much to do with the internals of Spring but rather the synchronization details between the thread that creates the context and the thread or threads that use the context once it has been created.
The Java memory model is based on the happens-before relation (Java Language Specification, ยง17.4.5) which is defined by various rules. For example, the call to Thread.start
made in one thread to start a new thread happens-before all actions in the newly started thread itself. So if your application's main thread first creates an application context, and then starts other threads for processing, then the processing threads are guaranteed to see the fully-initialized context.
Fields marked volatile
also impose a happens-before relation, in the sense that if thread A writes a value to a volatile
, any other thread that sees the result of that write is also guaranteed to see anything else that thread A did before it did the volatile write. Therefore if there isn't any explicit synchronization between the initialization thread and the processing threads then the following pattern would be sufficient to ensure safety
public class Setup {
private volatile boolean inited = false;
private ApplicationContext ctx;
public boolean isInited() { return inited; }
public ApplicationContext getContext() { return ctx; }
public void init() {
ctx = new ClassPathXmlApplicationContext("context.xml");
inited = true; // volatile write
}
}
public class Processor {
private void ensureInit() {
while(!setup.isInited()) { // volatile read
Thread.sleep(1000);
}
}
public void doStuff() {
ensureInit();
// at this point we know the context is fully initialized
}
}