【发布时间】:2012-11-15 16:04:53
【问题描述】:
Java 规范保证原始变量分配始终是原子的(long 和双 types 除外。
相反,与著名的i++ 递增操作相对应的Fetch-and-Add 操作将是非原子的,因为会导致读-修改-写操作。
假设这段代码:
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 )?考虑到它已经是原子的了。
【问题讨论】:
-
我的理解是,赋值的原子性只意味着 istore 是原子的——换句话说,在
a = b中,有可能读取b,然后突变为一个新值,然后原始值分配给a。但是,原子性保证a不会是b拥有的两个值的混合。 -
@assylias 这就是我的想法,我同意这个观点:)
标签: java x86 bytecode processor atomic