Kyle
Kyle

Reputation: 22045

Java - Thread Synchronization in a web app

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?

Upvotes: 1

Views: 2669

Answers (7)

Johnco
Johnco

Reputation: 4150

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

Upvotes: 2

cherouvim
cherouvim

Reputation: 31903

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;
    }
}

Upvotes: 5

duffymo
duffymo

Reputation: 308763

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.

Upvotes: 0

Chris
Chris

Reputation: 830

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.

Upvotes: 3

David Soroko
David Soroko

Reputation: 9086

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){...}

Upvotes: 0

Romain
Romain

Reputation: 12819

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.

Upvotes: 0

Yishai
Yishai

Reputation: 91881

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.

Upvotes: 1

Related Questions