Спецификация Java гарантирует, что присваивание примитивных переменных всегда атомарно (за исключением long
и двойного types
.
Наоборот, операция Выборка-и-Добавление соответствует знаменитой операции i++
приращения , будет неатомарным, поскольку приведет к операции чтения-изменения-записи.
Предполагая этот код:
public void assign(int b) {
int a = b;
}
Сгенерированный байт-код:
public void assign(int);
Code:
0: iload_1
1: istore_2
2: return
Таким образом, мы видим, что задание состоит из двух шагов (загрузка и сохранение).
Предполагая этот код:
public void assign(int b) {
int i = b++;
}
Байт-код:
public void assign(int);
Code:
0: iload_1
1: iinc 1, 1 //extra step here regarding the previous sample
4: istore_2
5: return
Зная, что процессор X86 может (по крайней мере, современные) выполнять операцию увеличения атомарно, как сказано:
В компьютерных науках инструкция ЦП «выборка и добавление» — это специальная инструкция, которая атомарно изменяет содержимое ячейки памяти. Он используется для реализации алгоритмов взаимного исключения и параллельных операций в многопроцессорных системах, являющихся обобщением семафоров.
Итак, первый вопрос: несмотря на то, что байт-код требует обоих шагов (загрузки и хранения), опирается ли Java на тот факт, что операция присваивания всегда выполняется атомарно, независимо от архитектуры процессора, и поэтому может обеспечить постоянную атомарность (для примитивных назначений) в своей спецификации?
Второй вопрос: неправильно ли подтверждать, что с очень современным процессором X86 и без совместного использования скомпилированного кода для разных архитектур вообще нет необходимости синхронизировать операцию i++
(или AtomicInteger
)? Считая его уже атомарным.
a = b
возможно, чтоb
читается, а затем преобразуется в новое значение, после чего исходное значение присваиваетсяa
. Однако атомарность гарантирует, чтоa
не будет смесью двух значений, хранящихся вb
. - person assylias   schedule 15.11.2012