53

I have multiple threads running which access singleton object and call its method and pass objects in it. In the method I do some calculations only on recieved object. I have heard that there would not be any problem in this case cause it is stateless and it is free for all.

My question is how it is free for all? I want to know how multiple threads can call the shared method in their own thread without overwriting the passed objects of other threads? Please explain in terms of memory allocation wise and at stack level.

class Singleton class{

    //no shared class or object variables and only one copy of this Singleton object exists.

    Object someMethod(Object o){
        //do some calculation or logic on the object o and return some string result
    }

}
Xtreme Biker
  • 28,480
  • 12
  • 120
  • 195
beinghuman
  • 1,981
  • 6
  • 24
  • 35
  • 1
    So glad there was a question like this. I was going crazy – Navin Nagpal Apr 04 '20 at 20:33
  • For anyone having doubts and needs a view regarding how it works at low level in memory consider reading this pure gold article. http://tutorials.jenkov.com/java-concurrency/java-memory-model.html – It's K Mar 13 '21 at 07:40

4 Answers4

73

I think you have to distinguish between what you've already stored in memory and code execution.

In a Singleton Object you have:

  • Fields: They are stored in memory. They can be shared amongst multiple threads and you have no guarantee they will keep consistent (unless you make them synchronized).
  • Methods to be called: They can be called from more than one thread. Each execution is independent and thread safe, unless they access some shared field improperly.

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.

Also if you write a Thread.currentThread().getId(); which basically returns the thread ID you're executing into singleton's methods, you will obtain different ids, because different threads are executing their own method stack. Being stateless means you've no fields into the singleton to be shared amongst them!

A word on Stateless and Stateful

Stateless means that the bean hasn't got any modifiable field to share. That means you have only methods or/and static stuff in your object, so you can use them anywhere and will always return you same result. You don't have to worry about synchronizing the access to the field.

That's a basic example about stateless, let's suppose you have a class that only performs the sum operation:

public class StatelessClass{

    public int sum(int a, int b){
        return a+b;
    }

}

In the same way, you can declare it as a abstract class (no instantiable itself) and make its methods static, which means you don't need any instance of it to call its methods:

public abstract class StatelessClass{

    /**
    *   I only sum objects
    */
    public static int sum(int a, int b){
        return a+b;
    }

}

Then you can use it as StatelessClass.sum(1,1);, this actually would be very similar to have a Singleton object itself, with the difference that in the Singleton you have a unique instance shared in the application.

In the same way, having a field which is injected and provides access to a service neither is considered to alter the state of the object:

public class StatelessServiceClass{

    private Service service;

    public int sum(int a, int b){
        return service.sum(a,b);
    }

    public void setService(Service serv){
        this.service=serv;
    }

}

However, having a field which is modifiable makes the Object stateful:

public class StatefulClass{

    //This fields make the object STATEFUL
    private int totalSum = 0;

    public int sum(int a, int b){
        int sum = a + b;
        totalSum = totalSum + sum;
        if (totalSum > 100)
            System.out.println("This thread "+Thread.currentThread().getId()+
                +" got it!");
        return sum;
    }

}

As sum can be accessed by multiple threads at the same time, you should guarantee that totalSum is accessed in a synchronized way. The printed sentence is not guaranteed to be true unless you do it.

All of this is also properly explained in this answer's Threadsafety piece by @BalusC.

Community
  • 1
  • 1
Xtreme Biker
  • 28,480
  • 12
  • 120
  • 195
  • I haven't downcasted it. – beinghuman Aug 31 '13 at 11:21
  • can you please tell me "Methods to be called: They can be called from more than one thread. Each execution is independent."...The singelton object is shared ,so isn't its method also shared?Please clear my confusion.. – beinghuman Aug 31 '13 at 11:31
  • If two objects `o1` and `o2` share the same member `m` it might no longer be thread-safe. So take care in this case. – Trinimon Aug 31 '13 at 11:40
  • 1
    @Xtreme Biker Perfectly explained..Thanks a lot – beinghuman Aug 31 '13 at 11:40
  • @XtremeBiker so you mean the methods will have no memory like the variables of class ?and if the object is stateless how its memory will be allocated coz it has no variables? – beinghuman Aug 31 '13 at 11:43
  • @XtremeBiker I know you are talking about properties.I just want to know if class has only properties ,how JVM will allocate memory to that object?also,The object reference holds some address,but what will it hold in this case?I hope you understand my confusion?Could You provide some links from where you read all these things. – beinghuman Aug 31 '13 at 11:49
  • @XtremeBiker I have flagged the question.probably moderator will look at it who down casted it.. – beinghuman Aug 31 '13 at 12:47
  • @XtremeBiker "Fields: They are stored in memory. They can be shared amongst multiple threads and you have no guarantee they will keep consistent" - What do you mean by consistent? If its a singleton, every thread will get the same instance which will hold onto the same field / member variable instance in every thread or does every thread create a copy of a singleton's member field / properties? e.g. if in Thread A, we switch the a member of the Singleton to some other instance, will Thread B when trying to access that same member of the Singleton find the new instance switched in Thread A? – Rickster Oct 20 '15 at 00:31
  • 2
    @XtremeBiker I have a doubt, could you please explain how spring handles this functionality? " every single thread will execute Singleton object's portion of code, wrapped in its own execution." How spring shares its object instance with different threads? – Dhananjayan Santhanakrishnan Feb 20 '16 at 12:49
8

Every thread has its own copy of the Object o and so even if multiple threads call the method at the same time, each method call of Thread will have its own stack allocated and the logic will apply there.

Why is it Thread Safe?

Thread Stacks are private to them and are by default thread safe as no other thread can enter in others stack.

NOTE: You can say that this Singleton of yours is Thread safe but not that the application is Thread safe as it also depends on whether the Object o being passed is itself thread safe or not. But as far as safety of Singleton is concerned it is thread safe.

Narendra Pathai
  • 38,384
  • 18
  • 73
  • 117
5

You can think about it in "pizza terms". You went to pizza cafe, and couple of other guys entered with you as well. Each one placed his order and then sat to his own table. Pizza boxes to be arrived then and each of you start eating his own meal.

Here, the cafe is a singleton, pizza boys are CPU cores, you and other customers are threads, orders and pizza are input and output data respectively, table is a piece of memory.

As you can see, each thread is served with his own piece of memory so CPU can distinguish your data and don't mix up. As you asked about stack, it's not a significant player here because each thread has it's own stack (as a part of your memory chunk).

Yury Schkatula
  • 4,650
  • 2
  • 16
  • 35
  • can you tell me how pizza store distinguish multiple orders?Well singelton class has only one method which is called by other threads and provided some data.How is this data not mixed? – beinghuman Aug 31 '13 at 11:35
  • Each pizza boy (one CPU core) has a list of his orders and iterates through it sequentially. You (as thread) has nothing to do by yourself with your order. All you need to do is been placed on that list, then a CPU core that is scheduled to serve you will do the rest: take your input data, perform all necessary calculations, deliver baked pizza then and arrange a payment finally. – Yury Schkatula Aug 31 '13 at 11:50
0
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;

    public class MainClass {
        public final static int MAX_THREAD = 20;
        public MainClass() {
            // TODO Auto-generated constructor stub
        }

        public static void main(String[] args) {

            List<Singleton> singletonList = new MainClass().createSingletonObjects();
            singletonList = Collections.synchronizedList(singletonList); 

            int index = 0;
            for (int i = 0; i < MAX_THREAD; i++) {

                Thread thread1 = new Thread(new MyThread(singletonList,index), "Thread"+i);
                thread1.start();
                index++;
            if (index == singletonList.size()) {
            index = 0;  
            }

            }

        }

    public synchronized List<Singleton> createSingletonObjects(){
        List<Singleton> listSingleton = new ArrayList<Singleton>();
            listSingleton.add(MySingleton1.getInstance());
            listSingleton.add(MySingleton2.getInstance());
            listSingleton.add(MySingleton3.getInstance());
            listSingleton.add(MySingleton4.getInstance());
            listSingleton.add(MySingleton5.getInstance());

            return listSingleton;

        }

    }


public class MySingleton1 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton1() {
        super();
        // TODO Auto-generated constructor stub
    }

    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton1();
            return mySingleton;
        }
        return mySingleton;
    }


public class MySingleton2 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton2() {
        super();
        // TODO Auto-generated constructor stub
    }

    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton2();
            return mySingleton;
        }
        return mySingleton;
    }







}


public class MySingleton3 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton3() {
        super();
        // TODO Auto-generated constructor stub
    }

    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton3();
            return mySingleton;
        }
        return mySingleton;
    }







}


public class MySingleton4 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton4() {
        super();
        // TODO Auto-generated constructor stub
    }

    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton4();
            return mySingleton;
        }
        return mySingleton;
    }







}


public class MySingleton5 extends Singleton{
    private static Singleton mySingleton;
    private MySingleton5() {
        super();
        // TODO Auto-generated constructor stub
    }

    public static Singleton getInstance() {
        if (mySingleton == null) {
            mySingleton = new MySingleton5();
            return mySingleton;
        }
        return mySingleton;
    }







}
Niraj
  • 21
  • 3
  • how multiple threads invoke limited singleton object's and work on them.In this sample I am showing n number of threads having access over 5 singleton objects. After every 5 threads it will reuse the existing sigleton objects. – Niraj Mar 03 '19 at 19:12