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