views:

119

answers:

7

I have a web app where I load components lazily. There is a lot of

static Bla bla;
...    
if(bla == null) 
    bla = new Bla();

spread throughout the code. What do I need to do to make sure this is thread safe? Should I just wrap anytime I do one of these initializations in a synchronized block? Is there any problem with doing that?

+2  A: 

Assuming you are using Java 1.5 or later, you can do this:

    private static volatile Helper helper = null;

    public static Helper getHelper() {
        if (helper == null) {
            synchronized(Helper.class) {
                if (helper == null)
                    helper = new Helper();
            }
        }
        return helper;
    }

That is guaranteed to be threadsafe.

I recommend you read this to understand why the var HAS to be volatile, and the double check for null is actually needed: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Johnco
You also have to be 100% sure your code gets compiled with the JDK5 compliance level, or the volatile part could get discarded, and the double-checked lock will be broken by design.
Romain
Thanks, and good article. All of the things I was trying to load were singletons, so I think I will go with the `class HelperSingleton {static Helper singleton = new Helper(); }` pattern described in the article.
Kyle
this is known as "Double-Checked Locking" and does not do what you want. See here for example http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.htmlOoops did not notice the `volatile`. Will work in 1.5 and onwards only if there is a single instance of the containing class.
David Soroko
You are synchronizing on `this` in a static method. Perhaps you've meant `MyObject.class`
Alexander Pogrebnyak
+1  A: 

The lazy instantiation is only really a part of the problem. What about accessing these fields?

Typically in a J2EE application you avoid doing this kind of thing as much as you can so that you can isolate your code from any threading issues.

Perhaps if you expand one what kind of global state you want to keep there are better ways to solve the problem.

That being said, to answer your question directly, you need to ensure that access to these fields is done synchronized, both reading and writing. Java 5 has better options than using synchronized in some cases. I suggest reading Java Concurrency in Practice to understand these issues.

Yishai
A: 

The best way is indeed to enclose everything in a synchronized block, and declare the variable volatile, as in:

private static volatile Bla bla;
synchronized{
    if(bla == null) bla = new Bla();
}

If you really need to have only one single instance assigned to the bla at any time you web application is running, you have to keep in mind the fact a static keyword applied to a variable declaration only ensures there will be one per classloader that reads the class definition of the class defining it.

Romain
A: 

Because bla is static, it can be accessed from different instances of the containing class and code like synchronized{...} or synchronized(this){...} does not defend against this. You must obtain a lock on the same object in all cases so for example synchronized(bla){...}

David Soroko
+3  A: 

It is tricky to use volatile variable.

It's described here: http://www.ibm.com/developerworks/java/library/j-dcl.html

Example cited from above link:

class Singleton
{
    private Vector v;
    private boolean inUse;
    private static Singleton instance = new Singleton();
    private Singleton()
    {
        v = new Vector();
        inUse = true;
        //...
    }
    public static Singleton getInstance()
    {
        return instance;
    }
}

will work 100% and is much more clear (to read and to understand) comparing to double checking and other approaches.

Chris
This looks like it would work good for me, are there any downsides to doing it this way? Why did people even bother with double-checked locking and such if you can just do it this way?
Kyle
@Spines: The downside is that this is not lazy loading.
cherouvim
@cherouvim: Referring to doing it that way, the article you provided says: The code in Listing 10 does not use synchronization and ensures that the Singleton object is not created until a call is made to the static getInstance() method.
Kyle
@Spines: That is wrong. The singleton object is created as soon as the Singleton class is loaded by the classloader, no mater whether you call getInstance() or not.
cherouvim
Sorry, I've missed the "lazy" part of question ;-)
Chris
+5  A: 

The best solution for lazy loading on a static field, as described in Effective Java [2nd edition, Item 71, p. 283] and Java Concurrency in Practice [p. 348], is the Initialization on demand holder idiom:

public class Something {
    private Something() {
    }

    private static class LazyHolder {
        private static final Something something = new Something();
    }

    public static Something getInstance() {
        return LazyHolder.something;
    }
}
cherouvim
A: 

I'd ask why you think it's necessary to load these lazily. If it's a web app, and you know you need these objects, why would you not want to load them eagerly once the app started up?

Please explain the benefit that lazy loading is providing. If it's static, is there ever a possibility that you won't initialize these objects? If the answer is no, I'd challenge the design and recommend that you load eagerly on start-up.

duffymo
Hi duffymo, the reason I am loading them lazily is because my app is on the Google App Engine (GAE). The GAE starts and stops instances of your app depending on the load to your site, and there is a chance that when a user requests a page they will have to wait for all initialization in your app to be done before getting a response. So what I do is: if the request happens on an instance that hasn't fully initialized yet, then I just serve the page out of the cache, without loading certain objects at all.
Kyle
Is the cache one of your lazily loaded objects? Wouldn't that be part of GAE? I see your point, thank you, but I'd wonder about the length of the init process and the chance that someone will be requesting a page when it happens. All that Singleton is buying you is the possibility that your user won't need all of the objects initialized when they make that request. If you can't guarantee that, this scheme can't help.
duffymo
Hi Duffymo, the cache wouldn't be lazily loaded, since I would need it on every request no matter what. The whole init process takes about 10 seconds, its very likely that another user would make a request in the middle of the init process. My goal is to keep serving out of the cache until the init process is done. Some examples of things that are lazily loaded, and wouldn't be needed if I served from cache are: JDO, which takes about 5 seconds to load, and the Spring Framework, which takes ~2 seconds. By lazily loading those, the user only has to wait ~3 seconds as opposed to ~10 seconds.
Kyle
Kyle
Lazy loading Spring? Are you suggesting that you're writing a class loader here? You wouldn't normally be loading that the way you would a Java singleton. You might be beyond me on this one, Spines. The GAE angle is introducing wrinkles that I wasn't thinking about when I first answered this question. Sorry I'm not more helpful.
duffymo