Что происходит, когда два потока вызывают один и тот же статический метод одновременно?
что происходит, когда два потока вызывают один и тот же статический метод, в то же время? Например:
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()
используя заданную стратегию синхронизации. Другими словами, ваша логика может дать неожиданные и непредсказуемые результаты, если вы пишете в одну и ту же переменную(ы), а затем читаете из двух потоков одновременно.