Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton Pattern in Multi threaded environment

During my interview, interviewer started his question with singleton pattern. I wrote below. Then, he asked Shouldn't we check for Nullity inside getInstance method?

I replied with, It is NOT necessary, since member is static type and is being initialized at the same time. But, seems like he was not satisfied with my answer.Am I correct or not ?

class Single {

        private final static Single sing = new Single();       
        private Single() {
        }        
        public static Single getInstance() {
            return sing;
        }
    }

Now, next question he ask to write singleton class for multi-threaded environment. Then, I wrote double check singleton class.

  class MultithreadedSingle {        
        private static MultithreadedSingle single;       
        private MultithreadedSingle() {
        }        
        public static MultithreadedSingle getInstance() {
            if(single==null){
                    synchronized(MultithreadedSingle.class){
                      if(single==null){
                            single= new MultithreadedSingle(); 
                              }      
                      }
                   }
             return single;
        }
    }

Then, he had an objection with using synchronized and double check and said It is useless. Why are you checking twice and why are you using synchronized ? I tried to convince him with multiple scenario. But, he didn't.

Later, at home I tried below code where I'm using simple singleton class with multiple thread.

public class Test {

    public static void main(String ar[]) {
        Test1 t = new Test1();
        Test1 t2 = new Test1();
        Test1 t3 = new Test1();
        Thread tt = new Thread(t);
        Thread tt2 = new Thread(t2);
        Thread tt3 = new Thread(t3);
        Thread tt4 = new Thread(t);
        Thread tt5 = new Thread(t);
        tt.start();
        tt2.start();
        tt3.start();
        tt4.start();
        tt5.start();

    }
}

final class Test1 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + Single.getInstance().hashCode());
        }
    }

}
     class Single {

        private final static Single sing = new Single();       
        private Single() {
        }        
        public static Single getInstance() {
            return sing;
        }
    }

Below is the output :

Thread-0 : 1153093538
Thread-0 : 1153093538
Thread-0 : 1153093538
Thread-0 : 1153093538
Thread-0 : 1153093538
Thread-4 : 1153093538
Thread-1 : 1153093538
Thread-2 : 1153093538
Thread-3 : 1153093538
Thread-3 : 1153093538
Thread-3 : 1153093538
Thread-3 : 1153093538
Thread-3 : 1153093538
Thread-2 : 1153093538
Thread-2 : 1153093538
Thread-2 : 1153093538
Thread-2 : 1153093538
Thread-1 : 1153093538
Thread-1 : 1153093538
Thread-1 : 1153093538
Thread-1 : 1153093538
Thread-4 : 1153093538
Thread-4 : 1153093538
Thread-4 : 1153093538
Thread-4 : 1153093538

So, question is, Is it necessary to use synchronize or/and double check method in multi-threaded environment ? It seems like my first code itself (without adding any extra line of code) was the answer for both question. Any correction and knowledge share will be appreciated.

like image 266
Ravi Avatar asked Aug 22 '15 05:08

Ravi


People also ask

Why singleton is not thread safe?

Is singleton thread safe? A singleton class itself is not thread safe. Multiple threads can access the singleton same time and create multiple objects, violating the singleton concept. The singleton may also return a reference to a partially initialized object.

What happens when two threads access singleton at the same time?

Now coming to your question: if you share your singleton object among multiple threads and access it concurrently, every single thread will execute Singleton object's portion of code, wrapped in its own execution.


1 Answers

1) Class #1 is good for multithreaded environment

2) Class #2 is a singleton with lazy initialization and double checked locking, it's a known pattern and it needs to use synchronization. But your implementation is broken, it needs volatile on the field. You can find out why in this article http://www.javaworld.com/article/2074979/java-concurrency/double-checked-locking--clever--but-broken.html

3) a Singleton with one method does not need to use lazy pattern, because its class will be loaded and initialized only at first usage.

like image 73
Evgeniy Dorofeev Avatar answered Sep 28 '22 04:09

Evgeniy Dorofeev