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

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

public static String someMethod(){

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

    return new String(result);
}

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

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

4 ответов


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

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 является локальной переменной, проблем не будет. Пока любое внешнее состояние гарантированно остается неизменным во время чтения, проблем быть не может.


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


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

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

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