Is this singleton thread safe?

Based on this section , I posted an interesting version of the Singleton template, an implementation of which is based on AtomicIntegers.

Questions:

  • Is this implementation correct and thread safe, and is it even possible to use Atomic Variables for thread synchronization and control?
  • Additional question: if this implementation is thread safe, do I really need a volatile for the 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: private constructor added, but this is not the point.

+4
source share
4 answers

Is this implementation correct and thread safe, and can you usually use Atomic Variables for thread synchronization and control?

This, however, is usually more complex and intense, as you need to wait in order to respond quickly to changes.

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

In this case, you are not due to the fact that AtomicInteger contains mutable fields that guarantee correct execution - before / after-after behavior.


Of course you can just use an enumeration that is thread safe and much simpler;)

 enum Singleton { INSTANCE; } 
+8
source

Is this implementation correct and thread safe, and is it even possible to use Atomic Variables for thread synchronization and control?

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

 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 waitait () also resolves the initialization race condition. (I also added a try-finally block to avoid deadlocks in the constructor exception.)

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

Not unless you call the appropriate AtomicInteger or CountDownLatch before accessing the instance variable. See what happened earlier in the documentation .

+2
source

T1 thread can be paused on instance = new Object(); , T2 will then fall into the else{} block since readyCounter has not yet been incremented. Thtat is not completely correct, since the completion of initialization is completed , which lags behind the state of accounting

0
source

I would rather make one synchronized block in your getInstance() method. It's enough. You do not need these strange counters, which are also not as safe as @ David noted.

0
source

Source: https://habr.com/ru/post/1435061/


All Articles