Temple Wing
Temple Wing

Reputation: 429

java concurrency in practice 16.7

This code is used to demonstrate double-checked-locking anti-pattern:

@NotThreadSafe
public class DoubleCheckedLocking {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null) {
            synchronized (DoubleCheckedLocking.class) {
                if (resource == null)
                    resource = new Resource();
            }
        }
        return resource;
    }
}

Can I just avoid this problem by modify it to:

@NotThreadSafe
public class DoubleCheckedLocking {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null) {
            synchronized (DoubleCheckedLocking.class) {
                if (resource == null){
                    Resource r=new Resource();
                    resource = r;
                }
            }
        }
        return resource;
    }
}

As far as I know,

Resource r=new Resource();
resource = r;

That compiler should provide happen-before relationship for that.

Upvotes: 1

Views: 203

Answers (3)

OldCurmudgeon
OldCurmudgeon

Reputation: 65869

The compiler is allowed to optimise:

Resource r=new Resource();
resource = r;

to

resource=new Resource();

so your adjustment is ineffective.

Upvotes: 2

ninjalj
ninjalj

Reputation: 43748

public static Resource getInstance() {
    if (resource == null) {
        synchronized (DoubleCheckedLocking.class) {
            if (resource == null){
                Resource r=new Resource();
                resource = r;
            }
        }
    }
    return resource;
}

The only thing that guarantees proper visibility between threads is creating synchronizes-with relationships via synchronization (via synchronized, volatile, ...).

If you don't have a synchronizes-with relationship, a thread is not required to see modifications from other threads.

In this case, a thread may create a Resource and store a reference to it in resource. Then a second thread may enter getInstance(), and see resource != null. This second thread is not guaranteed to see all the effects of resource's constructions, since it isn't synchronized-with the first thread.

Upvotes: 2

GreyBeardedGeek
GreyBeardedGeek

Reputation: 30088

As far as I know, the only known implementation of the double-checked locking pattern that works (for JDK5 and above) makes use of the 'volatile' keyword. See Fixing Double-Checked Locking using Volatile

Upvotes: 4

Related Questions