SingleTon class is not synchronized and returning multiple instances

techi :

There is something wrong with my code below. I am getting multiple instances of the same singleton class when calling it from multiple threads from the same process. I am expecting the program should print "Creating instance" only once but it is printing 3 times(i.e. per thread).

package SingleTon;

class SingleTon implements Runnable {
    String name;
    int salary;
    private static SingleTon singleTonInstance;

    SingleTon() {

    }

    public static SingleTon getInstance() {
        if (singleTonInstance == null) {
            synchronized (SingleTon.class) {
                System.out.println("Creating instance");
                singleTonInstance = new SingleTon();
            }
        }
        return singleTonInstance;
    }

    @Override
    public void run() {
        System.out.format("Thread %s is starting\n",Thread.currentThread().getName());
        getInstance();
    }

}

package SingleTon;

public class SingleTonDemo {

    public static void main(String[] args) {
        System.out.println("test");
        SingleTon t = new SingleTon();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        t1.start();
        t2.start();
        t3.start();
    }

}

Output:

test
Thread Thread-0 is starting
Thread Thread-2 is starting
Thread Thread-1 is starting
Creating instance
Creating instance
Creating instance
EJK :

You need to change the following:

1) Make your default constructor private. As written, it is package-private and can be called by other classes in the same package.

private SingleTon() {
}

Once you have done this, your SingleTonDemo class will no longer be able to call the constructor and will be forced to use the getInstance() method. Currently, each call to the constructor is creating a new instance.

2) Synchronize the entire getInstance() method. As written, 2 separate threads can get a null value for singleTonInstance, and thus each thread would create a new instance.

    public static SingleTon getInstance() {

2a) An alternate approach to ensuring there is only one instance of the class is to use static initialization. In the declaration of the static variable, you create the object:

private static SingleTon singleTonInstance = new SingleTon();

The JVM will ensure that this is called only one. That also improves your getInstance method as you would change it to:

public static SingleTon getInstance() {
    return singleTonInstance;
}

The advantage of this approach is that not only is the getInstance method simpler, it also does not incur the overhead of being synchronized.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=115255&siteId=1