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.