Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this Singleton a thread-safe one?

Basing on this topic, I put down an interesting version of Singleton pattern which implementation is based on AtomicIntegers.

The questions are:

  • is this implementation correct and thread-safe, and generally is it possible to use Atomic Variables for thread synchronization and management?
  • Additional question: if this implementation is thread-safe, do I really need a volatile modifier for instance variable?
public class StrangeSingleton
{

    private StrangeSingleton() {};

    private static volatile Object instance;

    private static AtomicInteger initCounter = new AtomicInteger();
    private static AtomicInteger readyCounter = new AtomicInteger();

    static Object getInstance()
    {

        if (initCounter.incrementAndGet() == 1)
        {
            instance = new Object();

            readyCounter.incrementAndGet();

            return instance;
        }
        else if (readyCounter.get() == 1)
        {
            return instance;
        }
        else
        {
            //initialization not complete yet.
            //write here some logic you want:               
            //sleep for 5s and try one more time,
            //or throw Exception, or return null..

            return null;
        }
    }
}

UPDATE: added the private constructor, but its not the point.

like image 275
KutaBeach Avatar asked Dec 27 '22 17:12

KutaBeach


2 Answers

is this implementation is correct and thread-safe, and generally is it possible to use Atomic Variables for thread synchronization and management?

Its is but it usually more complicated and cpu intensive as you need to busy wait to respond to changes quickly.

Additional question: if this implementation is thread-safe, do I really need a volatile modifier for instance variable?

In this case you don't because AtomicInteger contain volatile fields which will ensure correct happens-before/happens-after behaviour.


Of course you could just use an enum which is thread safe and much simpler ;)

enum Singleton {
    INSTANCE;
}
like image 199
Peter Lawrey Avatar answered Jan 05 '23 15:01

Peter Lawrey


is this implementation correct and thread-safe, and generally is it possible to use Atomic Variables for thread synchronization and management?

Yes, but for the readyCounter variable you should probably use a CountDownLatch, like this:

private static AtomicInteger initCounter = new AtomicInteger();
private static CountDownLatch readyCounter = new CountDownLatch(1);

static Object getInstance()
{

    if (initCounter.incrementAndGet() == 1)
    {
        try {
            instance = new Object();
            return instance;
        } finally {
            readyCounter.countDown();
        }
    }
    else
    {
        readyCounter.await();
        return instance;
    }
}

Calling await() also solves the initialization race condition. (I also added a try-finally block to avoid deadlocks on a constructor exception.)

Additional question: if this implementation is thread-safe, do I really need a volatile modifier for instance variable?

No, not if you call the relevant AtomicInteger or CountDownLatch functions before accessing the instance variable. Look for happens-before in the documentation.

like image 36
Soulman Avatar answered Jan 05 '23 15:01

Soulman