Singleton Invalidated by Multithreading

Singleton will work properly in multithreaded environment only if eager instantiation has been done because in this case instance creation will happen at the time of class loading only. But for Lazy instantiation we will have to take care of multiple things. If we want to delay the instantiation because of cost, we use to go with lazy.

Example

package com.loopandbreak.singleton;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingletonInvalidatedByMultithreading {

    private static SingletonInvalidatedByMultithreading singletonObject = null;

    private SingletonInvalidatedByMultithreading() {
        System.out.println("Creating Object.");
    }

    public static SingletonInvalidatedByMultithreading getInstance() {
        if (singletonObject == null) {
            singletonObject = new SingletonInvalidatedByMultithreading();
        }
        return singletonObject;
    }

    static void useSingleton() {
        SingletonInvalidatedByMultithreading obj = SingletonInvalidatedByMultithreading.getInstance();
        print(obj);
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(SingletonInvalidatedByMultithreading::useSingleton);
        executorService.submit(SingletonInvalidatedByMultithreading::useSingleton);
    }

    private static void print(SingletonInvalidatedByMultithreading obj) {
        System.out.println("Hashcode of object is " + obj.hashCode());
    }
}

When you run the above program many times you will notice that in multithreaded environment sometimes Singleton principle works but sometimes it violates.

Output

Creating Object.
Hashcode of object is 974798335
Creating Object.
Hashcode of object is 645970594

We are applying double check locking here and keeping the instance as volatile so that one state shared between multiple threads.

Example

package com.loopandbreak.singleton;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingletonInvalidatedByMultithreading {

    private static volatile SingletonInvalidatedByMultithreading singletonObject = null;

    private SingletonInvalidatedByMultithreading() {
        System.out.println("Creating Object.");
    }

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

    static void useSingleton() {
        SingletonInvalidatedByMultithreading obj = SingletonInvalidatedByMultithreading.getInstance();
        print(obj);
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(SingletonInvalidatedByMultithreading::useSingleton);
        executorService.submit(SingletonInvalidatedByMultithreading::useSingleton);
    }

    private static void print(SingletonInvalidatedByMultithreading obj) {
        System.out.println("Hashcode of object is " + obj.hashCode());
    }
}

Output

Creating Object.
Hashcode of object is 290209249
Hashcode of object is 290209249

Now, irrespective of how many times you execute this program, you’ll get same single instance for multiple threads.

Share

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *