Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Spring publish beans in thread-safe manner?

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?

like image 435
Marcin Avatar asked Aug 29 '13 11:08

Marcin


People also ask

Does Spring beans are thread-safe?

Are Spring Beans Thread Safe? No. Spring has different bean scopes (e.g. Prototype, Singleton, etc.)

Which beans are thread-safe in Spring framework?

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.

Are Spring beans multithreaded?

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.


1 Answers

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
  }
}
like image 171
Ian Roberts Avatar answered Sep 18 '22 14:09

Ian Roberts