Связь между инструкциями байт-кода и процессором
Спецификация Java гарантирует, что примитивные присвоения переменных всегда атомарны (ожидайте дляlong
и двойнойtypes
.
С другой стороны,Принеси-и-Add операция, соответствующая известной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++;
}
Bytecode:
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 может (по крайней мере, современные), атомарно работает приращение операции, как сказано:
В компьютерных науках инструкция CPU для извлечения и добавления - это специальная инструкция, которая атомарно модифицирует содержимое области памяти. Он используется для реализации взаимного исключения и параллельных алгоритмов в многопроцессорных системах, обобщение семафоров.
Итак, первый вопрос: Несмотря на тот факт, что байт-код требует обоих этапов (загрузка и хранение), полагается ли Java на тот факт, что операция присваивания является операцией, всегда выполняемой атомарно, независимо от архитектуры процессора, и поэтому может обеспечивать постоянную атомарность (для примитивных назначений) в своей спецификации?
Второй вопрос: Неправильно ли утверждать, что с очень современным процессором X86 и без совместного использования скомпилированного кода между различными архитектурами вообще не нужно синхронизироватьi++
операция (илиAtomicInteger
)? Учитывая это уже атомно.