Java 规范保证原始变量赋值始终是原子的(除了long
和双types
.
相反,获取并添加 http://en.wikipedia.org/wiki/Fetch-and-add对应著名的操作i++
增量操作将是非原子的,因为会导致读取-修改-写入操作。
假设这段代码:
public void assign(int b) {
int a = b;
}
生成的字节码为:
public void assign(int);
Code:
0: iload_1
1: istore_2
2: return
因此,我们看到作业由以下部分组成two步骤(加载和存储)。
假设这段代码:
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
)?考虑到它已经是原子的了。