Подтвердить что ты не робот

Как несколько потоков вызывают метод Singleton Object и работают над ними?

У меня есть несколько потоков, которые запускают один объект Singleton, и вызывают его метод и пропускают в нем объекты. В методе я делаю некоторые вычисления только на получаемом объекте. Я слышал, что в этом случае не было бы никаких проблем, потому что он без гражданства и свободен для всех.

Мой вопрос в том, как он свободен для всех? Я хочу знать, как несколько потоков могут вызывать общий метод в своем потоке без перезаписи переданных объектов других потоков? Пожалуйста, объясните с точки зрения распределения памяти и уровня стека.

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
    }

}
4b9b3361

Ответ 1

Я думаю, вам нужно различать то, что вы уже сохранили в памяти и исполнение кода.

В Singleton Object у вас есть:

  • Поля: они хранятся в памяти. Они могут быть разделены между несколькими потоками, и у вас нет гарантии, что они будут поддерживать последовательность (если вы не синхронизируете их).
  • Методы, которые будут называться: их можно вызывать из нескольких потоков. Каждое выполнение является независимым и потокобезопасным, если только они не имеют доступ к некоторому общему полю неправильно.

Теперь перейдем к вашему вопросу: если вы разделите свой одноэлементный объект между несколькими потоками и одновременно получите доступ к нему, каждый отдельный поток выполнит часть объекта Singleton кода, завернутую в его собственное исполнение.

Также, если вы пишете Thread.currentThread().getId();, который в основном возвращает идентификатор потока, который вы выполняете в методах singleton, вы получите разные идентификаторы, потому что разные потоки выполняют свой собственный стек методов. Являясь апатридом, у вас нет полей в синглтоне, которые будут использоваться среди них!

Слово о безгражданстве и состояниях

Без гражданства означает, что bean не имеет модифицируемого поля для обмена. Это означает, что у вас есть только методы и/или статические вещи в вашем объекте, поэтому вы можете использовать их в любом месте и всегда будете возвращать вам тот же результат. Вам не нужно беспокоиться о синхронизации доступа к полю.

В качестве базового примера о безстоящем, предположим, что у вас есть класс, который выполняет только операцию sum:

public class StatelessClass{

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

}

Точно так же вы можете объявить его как класс abstract (без его создания) и сделать его методы статическими, что означает, что вам не нужен какой-либо экземпляр для вызова его методов:

public abstract class StatelessClass{

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

}

Тогда вы можете использовать его как StatelessClass.sum(1,1);, это будет очень похоже на объект Singleton, с той разницей, что в Singleton у вас есть уникальный экземпляр, общий для приложения.

Таким же образом, если поле, которое вводится и обеспечивает доступ к службе, не считается измененным состоянием объекта:

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;
    }

}

Однако наличие изменяемого поля делает объект 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;
    }

}

В качестве sum можно обращаться несколькими потоками одновременно, вы должны гарантировать, что totalSum будет выполняться синхронизированным образом. Отпечатанное предложение не гарантируется, если вы не сделаете это.

Все это также правильно объяснено в этом ответе Threadsafety часть @BalusC.

Ответ 2

Вы можете думать об этом в "условиях пиццы". Вы отправились в кафе пиццы, и вместе с вами вошли еще несколько парней. Каждый поместил свой заказ, а затем сел за свой стол. Затем появятся коробки для пиццы, и каждый из вас начнет есть свою еду.

Здесь кафе - одноэлементный, мальчики-пиццы - это ядра процессора, вы и другие клиенты - это потоки, заказы и пицца - это входные и выходные данные соответственно, таблица - часть памяти.

Как вы можете видеть, каждый поток обслуживается своей собственной памятью, поэтому процессор может различать ваши данные и не смешиваться. Поскольку вы спрашивали о стеке, это не значительный игрок здесь, потому что каждый поток имеет свой собственный стек (как часть вашего куска памяти).

Ответ 3

Каждый поток имеет свою собственную копию Object o, поэтому даже если несколько потоков одновременно вызовут этот метод, каждый вызов метода Thread будет иметь выделенный собственный стек и там будет применяться логика.

Почему это потокобезопасно?

Потоки потоков являются частными для них и по умолчанию потокобезопасны, поскольку ни один другой поток не может входить в другой стек.

ПРИМЕЧАНИЕ. Вы можете сказать, что этот синглтон - это потокобезопасный, но не тот, что приложение является потокобезопасным, так как оно также зависит от того, является ли передаваемый Object o сам потоком безопасным или нет. Но что касается безопасности Singleton, это безопасно для потоков.