Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid constant synchronization during thread safe lazy initialization (not singleton solution)? [closed]

I am wondering what is the best approach for following situation:

Lets say, that we have some kind of factory MyUtilFactory returning cached instances of MyUtil class. Multiple instances of MyUtil are holded in a static Map<String,MyUtil> utilsCache.

And now, abstract flow for lazy creation should be as follows:

  1. if cache utilsCache is empty, perform first initialization - load instances to static cache map.
  2. get instance from cache
  3. check if retrieved instance is initialized
  4. if instance is not initialized, perform instance initialization (expensive)
  5. return instance.

Now, step 1 and 4 needs to be synchronized, as initialization is time consuming and it would be executed multiple times, however it is required only for the first initialization of cache and instance.

It is easy to put everything in synchronized block(or even method) and there would be no problem at all, however I would like to avoid synchronization where it is not needed.

One approach would be something like that

        if (!someObject.isInitialized()) { // check if it is ready without synchonization
            synchronized (someObject) { // its not ready so lets synchronize from here
                if (!someObject.isInitialized()) { //first thread will get the samo outcome, but other threads will not
                    performInitialization();
                }
            }
        }

Now the point of repeating the condition in synchronized block, is to allow first thread to perfom initialization. Any subsequent threads will wait for the first one to complete initialization, and than condition in synchronized if statment will not be fulfilled. It can be done just like that and it works preatty well, but I don't think it is the best and the most elegant approach for such issue. My question is, how to do it "the right way"

like image 203
Antoniossss Avatar asked Jan 08 '14 12:01

Antoniossss


1 Answers

Yes is the right way well known as double check locking read also

http://en.wikipedia.org/wiki/Double-checked_locking

there is a little problem with "someObject.isInitialized()": "someObject" must be volatile in java 6.

 private volatile SomeObject someObject= null;

Read this article it is very usefull

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

like image 68
venergiac Avatar answered Sep 28 '22 07:09

venergiac