My knowledge about JVM internals is that if references are not published correctly, there is a chance that different threads will see different values of the same fields.
My question is: Does Spring beans container guarantee safe publication? If not, should I make all my bean getters and setters synchronized
or use volatile
? Or maybe use final
fields and constructor initialization?
I assume that this may only be an issue for singleton beans as prototype beans are created on demand from requesting thread. Is my understanding correct?
Are Spring Beans Thread Safe? No. Spring has different bean scopes (e.g. Prototype, Singleton, etc.)
Singleton Beans is thread safe or not depends on how the class whose scope is singleton is written. Each calling thread will have its own execution and does not interfere with another thread's execution unless there is some code in the singleton scoped class which is shared by all calling threads.
It's possible for Spring to use the same bean instance in multiple threads, firstly because for each thread, Java creates a private stack memory. The stack memory is responsible for storing the states of the local variables used inside methods during thread execution.
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
}
}
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