Singleton Using AtomicReference

Is this a lazy initializing singleton implementation using AtomicReference? If not, what are the possible problems?

import java.io.ObjectStreamException; import java.io.Serializable; import java.util.concurrent.atomic.AtomicReference; public class Singleton implements Serializable { private static final Singleton _instance = new Singleton(); private static AtomicReference<Singleton> instance = new AtomicReference<Singleton>(); private Singleton() { } public static Singleton getInstance() { if (instance.compareAndSet(null, _instance)) { synchronized (_instance) { _instance.init(); instance.set(_instance); } } return instance.get(); } private void init() { // do initialization } private Object readResolve() throws ObjectStreamException { return getInstance(); } } 
+6
source share
6 answers

No, it is bad:

 public static Singleton getInstance() { // new "singleton" for every method call Singleton s = new Singleton(); ^^^^^^^^^^^^^^ if (instance.compareAndSet(null, s)) { synchronized (s) { s.init(); } } return instance.get(); } 

Using AtomicReference is a good idea, but it will not work because Java does not have a lazy rating.


Classic single-threaded post 1.5 methods:

Eager Singleton:

 public final class Singleton{ private Singleton(){} private static final Singleton INSTANCE = new Singleton(); public Singleton getInstance(){return INSTANCE;} } 

Lazy Singleton with an internal holder class:

 public final class Singleton{ private Singleton(){} private static class Holder{ private static final Singleton INSTANCE = new Singleton(); } public Singleton getInstance(){return Holder.INSTANCE;} } 

Enum Singleton:

 public enum Singleton{ INSTANCE; } 

You should probably stick to one of these

+10
source

You have a race condition in which you can return a Singleton instance before init will be called on it. You can wrap a singleton if you want init only once. However, we know how to implement single games in a simple, effective way, and volatile singletones are pure evil.

+1
source

You can prevent serialization script to make it power.

all your constructor should be private.

0
source

I don’t understand why you need to use AtomicReference for singleton: AtomicReference allows you to AtomicReference change to an object reference, and in the case of singleton there should be only one instance and no one should be able to change this again to run your application. Also, your code is not synchronized, so simultaneous requests will create multiple instances of the Singleton class (as indicated, for example, by @Sean Patrick Floyd).

0
source
 public static Singleton getInstance() { Singleton s=instance.get(); if(s!=null)synchronized(s){return s;}//already initialised ->return it Singleton s = new Singleton(); synchronized(s){ if(instance.compareAndSet(null, s))//try to set s.init(); } return instance.get();//use the one that is there after CaS (guaranteed not null) } 
0
source

Updated code adds deserialization using readResolve .

Two obvious issues here.

  • Backlinks can read the source object before calling readResolve.

  • Even if a class has only a private constructor, it is not final . final really important. A manual execution (or an implementation created using jig Singleton ) of an octet sequence can be deserialized into a subclass. (The no-args constructor of the most derived non-serializable base class (which should be available for most base serializable classes) is called by the deserialization machine.) Invalid readResolve not called for subclasses.

0
source

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


All Articles