Java 规范保证原始变量赋值始终是原子的(期望long
和 double types
.
相反,与著名的增量操作相对应的Fetch-and-Addi++
操作将是非原子的,因为会导致读-修改-写操作。
假设这段代码:
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
)是错误的吗?考虑到它已经是原子的。