3

Say Code for Singleton pattern:

class Singleton 
{ 
    private volatile static Singleton obj; 

    private Singleton() {} 

    public static Singleton getInstance() 
    { 
        if (obj == null) 
        { 
            synchronized (Singleton.class) 
            { 
                if (obj==null) 
                    obj = new Singleton(); 
            } 
        } 
        return obj; 
    } 
} 

obj in the above code is marked as Volatile, which means that whenever obj is used in the code, its always fetched from the main memory instead of using the cached value. So whenever if(obj==null) needs to be performed it fetches obj from main memory, though its value is set in the previous run. This is a performance overhead of using volatile keyword. How do we avoid it?

locke14
  • 1,335
  • 3
  • 15
  • 36
csr
  • 31
  • 1
  • avoid the double check if you don't need it.! – Kris Jul 10 '19 at 06:55
  • 1
    First of all, you are confusing `volatile` and `synchronized` block. Both provide the **atomicity** (means changes made by one thread are visible to others) but `synchronized` block also provides **Mutual Exclusion**, which means that it doesn't allow more than one thread to access it at a time. My point is `volatile` is used when you want atomicity but don't want mutual exclusion. You probably shouldn't use both in combination because it defeats the purpose of using `volatile` keyword. – Mushif Ali Nawaz Jul 10 '19 at 07:01
  • I think he wants to avoid double initialization in the case when multiple threads find obj to be null. – akshay202 Jul 10 '19 at 07:17
  • 1
    To add to @MushifAliNawaz, what you probably want is `volatile` and not `synchronized`. Technically, the only safe way to implement this `getInstance()` with the check is to use the `synchronized` block - if what you desire is to ensure that the constructor is invoked only once. That's the pattern you want to use when construction is heavy-weight, or should only happen one time for other reasons. It's also correct. Often, though, you want a single object of the type for other reasons - constructing two is fine, as long as only one is used. Then skip `synchronized` and use `volatile`. – Jens Finkhaeuser Jul 10 '19 at 07:19
  • @MushifAliNawaz "Both provide the atomicity" - nope, it should be "Both provide the _visibility_", a volatile variable is _not_ atomic. also "You probably shouldn't use both in combination because it defeats the purpose of using volatile keyword." - this is like saying don't use the DCL, this is at least inaccurate. – Eugene Jul 10 '19 at 07:24
  • @JensFinkhaeuser your comment is at least confusing. if you would just implement that `getInstance` with _only_ a synchronized block - you would potentially _acquire_ a lock for every single call; the entire point of DCL is not to do that - and do it only once. The `volatile` is a _must_ so that every thread will see the published and initialized instance. – Eugene Jul 10 '19 at 07:32
  • @Eugene Yep, you're right. Probably I should rephrase *atomic* to *visibility*. As far as I know, `volatile` keyword forces the processing environment to immediately flush to main memory changes that are made to variables so that those changes are visible to all threads. Probably it doesn't exactly match with the definition of *atomic*. – Mushif Ali Nawaz Jul 10 '19 at 07:33
  • @MushifAliNawaz _probably_? it does not match for a fact. the "flush" to main memory is a myth (though in practice it is close to that - as it drain the store buffer). The only guarantees that you can rely on are those that are stipulated in the `JLS` for `volatile`. – Eugene Jul 10 '19 at 07:35
  • @Eugene sure, the point of DCL is to try and avoid acquiring a lock. It's an optimization, no more. The OP is about the confusion of `volatile` and `synchronized`, so there's very little need to bring DCL into the picture. With respect to `volatile` being a must, that's precisely what I mean. It only is if you have very specific requirements that countless examples don't have, namely that you instantiate the singleton class only once. Most are content with looser requirements, which can skip `volatile`. I would not recommend it, but it's possible. – Jens Finkhaeuser Jul 10 '19 at 15:30
  • @JensFinkhaeuser even here in your explanation, you mention - `Most are content with looser requirements, which can skip volatile` and I wonder... do you mean `volatile` can be skipped in case of DCL? Cause if you are - you are plain wrong. If you mean that there are other ways to get a singleton - I would agree. Carefully choosing words in such a sensible matter, matters the most. – Eugene Jul 10 '19 at 15:35

4 Answers4

4

You have a serious miss-understanding what volatile does, but to be fair the internet and stackoverflow including is just polluted with wrong or incomplete answers about this. I also admit that I think I have a good grab about it, but sometimes have to re-read some things again.

What you have there shown - is called the "double check locking" idiom and it's a perfectly valid use-case to create a singleton. The question is if you really need it in your case (the other answer has shown a far more simple way, or you can read the "enum singleton pattern" too if you want). It's a bit funny how many people know that volatile is needed for this idiom, but can't really tell why it is needed.

DCL is doing two things mainly - ensures atomicity (multiple threads can't not enter the synchronized block at the same time) and ensures that once created, all threads will see that created instance, called visibility. At the same time, it ensures that the synchronized block will be entered a single time, all threads after that will not need to do that.

You could have easily done it via:

  private Singleton instance;

  public Singleton get() {
    synchronized (this) {
      if (instance == null) {
        instance = new Singleton();
      }
      return instance;
    }
  }

But now every single Thread that needs that instance has to compete for the lock and has to enter that synchronized block.

Some people think that: "hey, I can work around that!" and write (thus enter the synchronized block only once):

  private Singleton instance; // no volatile

  public Singleton get() {
    if (instance == null) {  
      synchronized (this) {
        if (instance == null) { 
          instance = new Singleton();
        }
      }
    }
    return instance; 
  }

As simple as that is - that is broken. And this isn't easy to explain.

  • it is broken because there are two independent reads of instance; JMM allow for these to be re-ordered; thus it is entirely valid that if (instance == null) does not see a null; while return instance; sees and returns a null. Yes, this is counter-intuitive, but entirely valid and provable (I can write a jcstress test to prove this in 15 minutes).

  • the second point is a bit more tricky. Suppose your singleton has a field that you need to set.

Look at this example:

static class Singleton {

    private Object some;

    public Object getSome() {
        return some;
    }

    public void setSome(Object some) {
        this.some = some;
    }
}

And you write code like this to provide that singleton:

private Singleton instance;

public Singleton get() {
    if (instance == null) {  
        synchronized (this) {
            if (instance == null) { 
                instance = new Singleton();
                instance.setSome(new Object());
            }
        }
    }
    return instance; 
}

Since the write to the volatile (instance = new Singleton();) happens before setting the field that you need instance.setSome(new Object());; some Thread that reads this instance might see that instance is not null, but when doing instance.getSome() will see a null. The correct way to do this would be (plus making the instance volatile):

 public Singleton get() {
    if (instance == null) {
        synchronized (this) {
            if (instance == null) {
                Singleton copy = new Singleton();
                copy.setSome(new Object());
                instance = copy;
            }
        }
    }
    return instance; 
}

Thus volatile here is needed for safe publication; so that the published reference is "safely" seen by all threads - all it's fields are initialized. There are some other ways to safely publish a reference, like final set in the constructor, etc.

Fact of life: reads are cheaper than writes; you should not care what volatile reads do under the hood as long as your code is correct; so don't worry about "reads from main memory" (or even better don't use this phrase without even partially understanding it).

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • You do misunderstand what `volatile` is about, though your explanation still works well enough. What `volatile` does precisely, and which is reflected in the "visibility" explanation is that it will always fetch the variable value from main memory, even if it's already in the CPU cache. Stores get flushed to main memory anyway; `volatile` has little influence on that. This *does* have an effect on what the compiler can do with regards to re-ordering. However, `volatile` *does* incur a significant performance overhead for reading in multi-threaded applications. – Jens Finkhaeuser Jul 11 '19 at 08:39
  • You don't strictly speaking need `volatile` OR `synchronized` if you can somehow ensure that the first write creating the Singleton instance happens before any other thread tries to read the instance variable. Any other thread will try to fetch the value from cache, fail, and retrieve it from main memory anyway. Where this is very dangerous is when you can't ensure this, or when you're dealing with a variable that gets modified a lot, i.e. not a Singleton. – Jens Finkhaeuser Jul 11 '19 at 08:41
  • Don't worry about the Object members (`getSome()/setSome()` and the underlying `some`) too much, though. The instance variable only holds a reference to the Singleton object in memory. That is, as long as the Singleton stays the same object, you'll always reference the same memory, which makes using the CPU cache safe. However, if `setSome()` is called a lot, I'd very definitely make the `some` member `volatile`, for the reasons outlined above. – Jens Finkhaeuser Jul 11 '19 at 08:43
  • TL;DR is, if in doubt always use `volatile` for ensuring values are always the same across threads. There is a distinct performance hit, but that only matters if you access the value *a lot*, and you care each time whether it's the freshest. – Jens Finkhaeuser Jul 11 '19 at 08:45
  • `synchronized` on the other hand ensures that the `new Singleton()` line only gets executed once. That's vital when creating the Singleton is expensive, or when you can't otherwise ensure reading threads happen after the instance gets created (see first comment). If in doubt, use that. And if you use both, DCL will make sure the `synchronized` block will not be entered unnecessarily, which helps with performance. – Jens Finkhaeuser Jul 11 '19 at 08:47
  • I expect @Eugene to argue a bit, but I'm not going to respond - there's too little light in the day to spend on that conversation. – Jens Finkhaeuser Jul 11 '19 at 08:48
  • @JensFinkhaeuser thx for the comments, pity you don't want to chat about it more, though... – Eugene Jul 11 '19 at 09:01
0

If you want to avoid using volatile, Then you can initialize when class loading and use private constructor to avoid creating new instance.

public class Singleton{
    //Initialized when class loading
    private static final Singleton INSTANCE = new Singleton();

    //To avoid creating new instance of Singleton
    private Singleton(){}

    public static Singleton getSingleton(){
        return INSTANCE;
    }
}
Rowi
  • 545
  • 3
  • 9
  • 2
    what will happen if this is a distributed application (running on multiple processors)? It will create multiple separate instances. That's why there is a concept of `volatile`. – Mushif Ali Nawaz Jul 10 '19 at 07:11
  • 1
    @MushifAliNawaz what do you mean _multiple_ separate instances? this is a singleton - one per classloader. what do you also mean "distributed application (running on multiple processors)"? – Eugene Jul 10 '19 at 07:22
  • @MushifAliNawaz, Singleton is supposed to have one instance. But that does not ensure that there is just one instance per JVM, it only ensures that there is one instance per classloader. when using multiple classloaders, each has its own. – Rowi Jul 10 '19 at 07:33
0

You can use Lazy initialization with Holder static class

class Singleton 
{ 

    private Singleton() {} 

    private static class LazyLoader{ 
        static final Singleton obj = new Singleton();
    }

    public static Singleton getInstance() 
    { 
        return LazyLoader.obj;
    } 
} 

The important thing to note here is that the constructor should be fail-safe otherwise class loader will throw NoClassDefFoundError

akshay202
  • 586
  • 1
  • 5
  • 23
0

You should use Enums for Singleton implementation.

Joshua Bloch suggests the use of Enum to implement Singleton design pattern because Java will ensures that any enum value is instantiated only once in a Java program. The drawback is that the enum type is somewhat inflexible; for example, it does not allow lazy initialization.

public enum EnumSingleton {
    INSTANCE;
    int value;
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
}
public class EnumDemo {
    public static void main(String[] args) {
        EnumSingleton singleton = EnumSingleton.INSTANCE;
        System.out.println(singleton.getValue());
        singleton.setValue(2);
        System.out.println(singleton.getValue());
    }
}

This post by has nicely listed other benefits of using Enums: java singleton instantiation

user
  • 867
  • 9
  • 21