Basing on this topic, I put down an interesting version of Singleton pattern which implementation is based on AtomicIntegers.
The questions are:
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.
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With