1
\$\begingroup\$

I'd like someone to double-check my use of Atomic primitives, because multi-threading is hard.

What I don't want to do is locking the whole get method, or having too many pre-checks per get() call.

private final static AtomicReference<T> REFERENCE = new AtomicReference<>();

private final static AtomicBoolean IS_CREATED = new AtomicBoolean(false);

public static MyObject get() {
    if (IS_CREATED.compareAndSet(false, true)) {
        REFERENCE.set(new MyObject());
    }
    return REFERENCE.get();
}
\$\endgroup\$
4
\$\begingroup\$

As vnp points out, your code is incorrect because a thread may read REFERENCE after IS_CREATED is set but before REFERENCE is set. Here are a couple alternatives:

  • use double-checked locking:

    private static volatile T reference;
    public static T get() {
        if (reference == null)
            synchronized(ThisClass.class) {
                if (reference == null)
                    reference = new MyObject();
            }
        return reference;
    }
    
  • use static class initialization:

    private static class Lazy {
        private static final T reference = new MyObject();
    }
    public static T get() {
        return Lazy.reference;
    }
    
  • use optimistic creation with CAS (this might create multiple instances but only one instance will be returned):

    private static final AtomicReference<T> reference = new AtomicReference<>();
    public static T get() {
        if (reference.get() == null)
            reference.compareAndSet(null, new MyObject());
        return reference.get();
    }
    
\$\endgroup\$
2
\$\begingroup\$

Feels like the question belongs to stack overflow.

That said, the method is not correct. Consider the scenario:

thread 1 executes compareAndSet; IS_CREATED becomes true
thread1 is suspended
thread 2 executes compareAndSet; IS_CREATED is true!
thread 2 returns REFERENCE.get() on an initialized reference
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.