1

So in my current project I have code like this:

private static final Object LOCK_OBJECT = new Object();
    private static Service getEntryPoint() {

    synchronized (LOCK_OBJECT) {
        if (entryPoint != null) {
            return entryPoint;
        }
        return new Service();
    }
}

My question is: what's the difference between this approach and "classic" singleton aproach: And what is actually the idea behind this lock object in this case?

    private static Service initializeEntryPoint() {

    if (entryPoint == null) {
        synchronized (Service.class) {
            if (entryPoint == null) {
                entryPoint = new Service();
            }
        }
    }
    return entryPoint;
}
kamil.rak
  • 1,378
  • 1
  • 14
  • 28

2 Answers2

0

Based on your question 1. what is actually the idea behind this lock object in this case?

  1. when we do synchronized (Service.class) in your singleton class, then you can use Service.class in some other class's synchronized block and call to your singleton will be till that synchronized didn't exit because Service.class return same Class class object.

  2. on the other hand when you write like below, this is local to you class and only your class have access to this object hence its not effected by other synchronized block.

    Object LOCK_OBJECT = new Object()
    

Regarding 2nd question why double if (entryPoint == null) check.

  1. in that case if 2 thread enters your method and both check if (entryPoint == null) then both will enter synchronized block one by one and you will have 2 object breaking the singleton contract.

  2. When you have addition check inside synchronized block then thats guarantee that even multiple thread came inside 1st check they will not scape from 2nd check.

For more details check: Double Checked Locking in Singleton

Best use Enum to create you singleton class see Implementing Singleton with an Enum (in Java):

public enum MySingleton {
     INSTANCE;   
}
Sumit Singh
  • 15,743
  • 6
  • 59
  • 89
  • You missed the actual key difference: two vs. one `entryPoint == null` checks. – luk2302 Nov 29 '19 at 09:59
  • Yes, still writing the answer :P, but mainly regarding why internal lock vs external i tried to and first – Sumit Singh Nov 29 '19 at 10:01
  • 1
    a) is not a valid excuse, you should post the answer when you are done writing it, not refine / change it over and over again just to be the [fastest gun](https://meta.stackexchange.com/questions/9731/fastest-gun-in-the-west-problem) b) the internal / external is basically irrelevant. – luk2302 Nov 29 '19 at 10:02
  • i think its irrelevant for you, but @kamil.rak ask in his question "behind this lock object in this case" – Sumit Singh Nov 29 '19 at 10:10
0

In both case the idea behind synchronization is to prevent calling the getEntryPoint method by two threads simultaneously for the first time. In this case if you dont put synchronization you end up with two instances of the singleton object.

Niw thats the theory.

In practice the first version is completely broken because you dont store the created Service instance and if you call it again the new service instance will be created.

The second seems to work but suffers from possible compiler optimizations (read the article)

So the best would be just an eager initialization. Easy and effective

public class Singleton {
  public static final Singleton INSTANCE = new Singleton();

  private Singleton() {}

}

Its worth mentioning that nowaday singletons implemented like this are considered anti pattern and you should consider organizing the code in a way where these objects will be injected to the code that requires them (by some DI container like spring guice, etc) or manually.

Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97