Thread Safe Double Checked Locking Singleton Object

Synchronization will make sure only a single thread will access the getAppleInstance method at a time. The object creation code is a single line, but still, Synchronized method will not let more than 1 thread access the method, every time a thread needs the Synchronized object, it has to acquire the lock of the getInstance method and all thread has to be in waiting for the resource to get free and eventually slows down the performance of the method.

package org.wesome.dsalgo.design.pattern.singleton;

import java.util.Objects;

public class Apple {
    static Apple appleInstance;

    public Apple() {
        System.out.println("Apple default constructor");
    }

    public static synchronized Apple getAppleInstance() {
        System.out.println("Apple getAppleInstance");
        if (Objects.isNull(appleInstance)) {
            if (Objects.isNull(appleInstance)) {
                appleInstance = new Apple();
            }
        }
        return appleInstance;
    }
}
package org.wesome.dsalgo.design.pattern.singleton;

class AppleThread extends Thread {
    public void run() {
        Apple apple = Apple.getAppleInstance();
        System.out.println("Object created by " + Thread.currentThread().getName() + " is " + apple);
    }
}

public class SingletonClass {
    public static void main(String[] args) {
        AppleThread AppleThread1 = new AppleThread();
        AppleThread AppleThread2 = new AppleThread();
        AppleThread1.start();
        AppleThread2.start();
    }
}
plugins {
    id 'java'
    id "io.freefair.lombok" version "6.4.1"
}

group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}

test {
    useJUnitPlatform()
}

 

Double Locked Singleton Object creation is antipattern and should be avoided. Bill Pugh Singleton Solution or Holder Singleton Pattern is adviced

The method Synchronization will add slowness to the application due to the cost associated with the Synchronized method, every time a new thread needs an instance of Singleton object, it has to wait for the lock to get released.

To avoid Synchronization of the entire getAppleInstance method, the block Synchronization can be used to Synchronize the object creation code or critical section only so that multiple threads can access the method at a time, but only 1 will be allowed to create an object.

Before Java 1.5, Double Checked Locking was failing due to happens-before relationship

in the below scenario, there can be multiple threads requested for Synchronizaed method getAppleInstance, hence a double lock of the object needs to be placed to make sure Singleton the instance has not been created by some other thread as shown below.

package org.wesome.dsalgo.design.pattern.singleton;

import java.util.Objects;

public class Apple {
    static Apple appleInstance;

    public Apple() {
        System.out.println("Apple default constructor");
    }

    public static Apple getAppleInstance() {
        System.out.println("Apple getAppleInstance");
        if (Objects.isNull(appleInstance)) {
            synchronized (Apple.class) {
                if (Objects.isNull(appleInstance)) {
                    appleInstance = new Apple();
                }
            }
        }
        return appleInstance;
    }
}
package org.wesome.dsalgo.design.pattern.singleton;

class AppleThread extends Thread {
    public void run() {
        Apple apple = Apple.getAppleInstance();
        System.out.println("Object created by " + Thread.currentThread().getName() + " is " + apple);
    }
}

public class SingletonClass {
    public static void main(String[] args) {
        AppleThread AppleThread1 = new AppleThread();
        AppleThread AppleThread2 = new AppleThread();
        AppleThread1.start();
        AppleThread2.start();
    }
}
plugins {
    id 'java'
    id "io.freefair.lombok" version "6.4.1"
}

group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}

test {
    useJUnitPlatform()
}

Pros of Double Locking

Performance degradation due to Synchrnozation will be overcome.

 

follow us on