Что происходит, когда два потока одновременно называют один и тот же статический метод?

Что происходит, когда два потока одновременно называют один и тот же статический метод? Например:

public static String someMethod(){

    //some logic, can take about 1 second to process

    return new String(result);
}

Первый поток вызывает someMethod(). Второй поток вызывает someMethod() через 0,5 секунды (первый поток по-прежнему обрабатывает данные).

Я знаю, что someMethod() можно синхронизировать. Но что произойдет, если он не синхронизируется?

Ответ 1

Это зависит от того, изменяется ли ваш метод вне состояния.

static long i = 0l;
public static String someMethod(){
    String accm = "";
    for(;i < Integer.MAX_VALUE*20/*Just to make sure word tearing occurs*/; i++)
        accm += i
    return accm;
}

Вызвать проблемы:

  • Длинны не гарантированно устанавливаются атомарно, поэтому их можно "разрывать" (Spec)
  • ++ не является атомной операцией. Это точно так же, как {int n = i; i = i + 1; return n}
    • i = i + 1 также не является атомарным, если он изменяется в середине, некоторые значения будут повторяться
    • Возврат n может быть устаревшим

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

Ответ 2

Когда вызывается метод, JVM создает стоп-фрейм для вызова в исполняемом потоке. Этот кадр содержит все локальные переменные, объявленные в методе. В случае любого метода, статического или иного, который не имеет доступа к полям, каждое выполнение выполняется полностью независимо от каждого потока. Если метод использует параметры в своем вычислении, эти параметры также находятся в кадре стека, а несколько вызовов не мешают друг другу.

Ответ 3

Тот факт, что метод статичен, не имеет значения. Они должны задавать вопрос о том, какие переменные состояния обрабатываются данным кодом.

  • Если никакие члены какого-либо экземпляра/класса не читаются/не записываются, тогда проблем не должно быть.
  • В случае операций записи необходима некоторая синхронизация
  • Если есть только чтения, это не обязательно означает, что метод хорошо синхронизирован. Это зависит от того, как записываются данные и по какому потоку. Если, например, код считывает V, который защищен монитором M во время операции записи, тогда чтение V должно также синхронизироваться на том же мониторе.

Ответ 4

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