Поведение статического метода в многопоточной среде в java

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

class Clstest{

    public static String testStaticMethod(String inFileStr) {

        // section 0

        // section 1

        // do something with inFileStr

        // section 2

        // section 3

        return inFileStr;

    }

}

Предположим, что существует пять потоков, каждый из которых выполняет вызов Clstest.testStaticMethod("arg-n") в то же время.

Тема 1 вызывает Clstest.testStaticMethod("arg-1").

Когда поток 1 находится в разделе 1, поток 2 вызывает Clstest.testStaticMethod("arg-2").

Тогда что будет с Thread 1? Будет ли он переходить в состояние сна?

Когда Thread 1 получил шанс, он возобновит выполнение из раздела 1, где он был приостановлен?

Как это происходит, когда один Clstest.testStaticMethod и один и тот же Clstest.testStaticMethod разделяются между всеми пятью нитями?

Есть ли возможность обменять inFileStr на несколько потоков?

Ответ 1

Ответ Hans Passant хорош. Но я подумал, что попытаюсь объяснить на чуть более простом уровне для любого, кто сталкивается с этим и является новым для Java. Здесь идет..

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

Когда поток начинает запускать новый метод, он сохраняет аргументы и локальные переменные в этом методе в своем стеке. Некоторые из этих значений могут быть указателями на объекты в куче. Если два потока работают по одному и тому же методу в то же самое время, они оба будут иметь указатели на их указатели на этот метод и иметь свои собственные копии аргументов и локальных переменных на своих стеках. Они будут только мешать друг другу, если вещи на их стеках указывают на одни и те же объекты в куче. В этом случае могут произойти всевозможные вещи. Но, как указывает Ханс, строки являются неизменными (не могут быть изменены), поэтому мы в безопасности, если это единственный объект, который является "общим".

Так много потоков могут работать по одному и тому же методу. Они могут не работать одновременно - это зависит от того, сколько ядер у вас на вашем компьютере, поскольку JVM сопоставляет потоки Java потокам ОС, которые запланированы на аппаратные потоки. Поэтому у вас мало контроля над тем, как эти потоки чередуются без использования сложных механизмов синхронизации.

Обратите внимание, что сон - это то, что поток делает для себя.

Ответ 2

Будет ли он переходить в режим ожидания?

Нет, запуск потока не влияет на другие потоки, если они не намеренно синхронизируются друг с другом. Если у вас более одного ядра процессора, все последние машины работают, эти потоки могут выполняться в одно и то же время. Это становится менее вероятным, когда вы начинаете 5 потоков, так как на вашем компьютере может не хватить ядер. Операционная система вынуждена выбирать между ними, давая им время для запуска. Задача планировщика потоков. Поток тогда не будет находиться в состоянии "сна", он просто приостанавливается и ожидает, когда планировщик потоков даст ему возможность запускать. Он возобновится там, где он был прерван планировщиком.

Есть ли возможность обменять inFileStr, отправленный несколькими потоками?

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

Нет такой гарантии, если аргумент является ссылкой на другой тип изменяемого объекта. Или если сам метод использует переменные, которые являются статическими или ссылаются на объекты в куче. Синхронизация требуется, когда поток изменяет объект, а другой поток читает его. Ключевое слово блокировки на языке С# - это шаблонный способ реализации такой необходимой синхронизации. Тот факт, что метод статичен, не означает, что такая синхронизация никогда не требуется. Это менее вероятно, так как вам не нужно беспокоиться о том, что потоки обращаются к одному и тому же объекту (разделяя это).