Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC Singleton thread safety?

I have a singleton Spring bean (default scope). So, one instance will be used by multiple threads. However, I'm a bit confused with regards thread safety, apparently all Spring beans are thread safe if they are stateless, but my bean is not stateless, it has various instance variables which are used by each request/other controllers/classes.

Here is the beginning of my singleton bean:

public class PcrfSimulator {

private final CustomGxSessionIdCacheImpl gxSessionIdCache = new CustomGxSessionIdCacheImpl();
private final PcrfRecord pcrfRec = new PcrfRecord();
private final ResponseConditions responseConditions = new ResponseConditions();

public CustomGxSessionIdCacheImpl getGxSessionIdCache() {
    return gxSessionIdCache;
}

public ArrayList<Rule> getRules() {
    return pcrfRec.getRules();
}

So, the fields above will be accessed by multiple threads - is it enough to mark these fields as volatile, or do I have to mark the methods which access them (there are a lot in not only this class, but other controllers/classes as well) with synchronized and use wait/notify etc?

Many thanks!

like image 314
Rory Avatar asked Feb 21 '12 10:02

Rory


2 Answers

Spring itself makes sure to properly publish your beans once they have been instantiated, injected, etc. This means that any thread having a reference to your singleton bean will at least see its state as it was at the end of the Spring context creation.

If the state is immutable, you don't have anything to do.

If the state of the singleton is mutable, you will have to properly synchronize the accesses to this mutable state, though.

like image 94
JB Nizet Avatar answered Sep 17 '22 20:09

JB Nizet


volatile does not help. It would only make sure that the value is really updated.

Volatile means (http://www.javamex.com/tutorials/synchronization_volatile.shtml):

  • The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory";
  • Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.

Making the method synchronized will only help if your control flow never exit the (outer) synchronized block between the first write and the last read to the shared variables, and all shared variables are only accessed within synchronized blocks that use the same lock object.

So the general solution is to prevent shared variables in this scenario. One easy way to make the class immutable is to use local variables and method parameters instead of shared instance variables.


You wrote "Spring beans are thread safe if they are stateless, but my bean is not stateless." -- Ok that theme is discussed in the paragraph above.

But in from your code is seams that this is not the problem! The variables marked with final so they are immutable. If the fields of that object behaves in the same way (are not updated or are adequate protected against concurrent modification problems) you do not have mutable shared variables. Sometimes this is called "effective stateless". This means the values are not changed. So this is no problem for concurrency, (because the concurrency problem is about changing values).

In the end: You can use this effective stateless class from the example in different threads without a synchronized block if the fields (PcrfRecord...) are effective stateless. (If the fields PcrfRecord... are not stateless then the class PcrfSimulator can not been called effective stateless) -- But this has noting to to with Spring, it is plain Java.

Btw: if your variable is final you do not need to make them volantile.

like image 21
Ralph Avatar answered Sep 18 '22 20:09

Ralph