Thread Safe Singleton Object or Draconian Synchronization

The getAppleInstance method will make sure if the object of the Singleton class is null then only it will create a new one else will return the existing one.

In single threaded environment getAppleInstance will work fine, but in multithreaded environment, there might be a chance that 2 different threads will call getAppleInstance at the same time for which if (Objects.isNull(appleInstance)) will return true and getAppleInstance will return 2 Singleton objects 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)) {
            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();
    }
}

To avoid single threaded creating multiple Singleton objects in  multithreaded environment, the getAppleInstance can be synchronized to make sure only 1 thread will execute at a time and only 1 Singleton object will be created 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 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()
}

Pros of Synchronized Method
Only 1 thread will be able to access the getInstance method.

Cons of Synchronized Method

Method Synchronization will bring the performance down.

follow us on