正如许多开发人员所知,增量运算符不是原子的。
例如:
public void incrementId(){ // id being an int field
id++;
}
实际上,这对应于三个不同的操作:
int temp = id;
id = id + 1;
id = temp;
此外,此方法的行为类似:
public void incrementId(){ // id being an int field
id = id + 1; // three steps also here
}
我的问题是:
在两个操作之间,场景背后的真正区别是什么:
id = id + 1; //three steps => non atomic
id = anotherIntVariable + 1; // one step => atomic
什么概念迫使编译器将第一个转换为3个步骤而不是另一个?
答案 0 :(得分:2)
什么概念迫使编译器将第一个转换为3 步骤而不是其他步骤?
不是,id = xyz + 1
将被编译为以下字节代码:
7 iload_2 [xyz]
8 iconst_1
9 iadd
10 istore_1 [id]
从字节代码中很容易看出上面不是“一步”
答案 1 :(得分:1)
没有什么可说的:
id = anotherVariable + 1
不会分3个步骤执行。但无论你运行多少次上面的代码,最终结果总是相同的(变量id
的值总是anotherIntVariable
加上1),如示例中所示id = id + 1
,id
变量的先前设定值会带来新的id
值,如果您遇到竞争条件,id
的结束值可能不是您所期望的
一些注意事项:
id
变量,无论您如何设置它,都需要同步它。总是,或者根本不设置值(参见Java Concurrency in Practice的第3章)。或者,您可以将id
变量设为volatile; id
时才有意义。如果不是这种情况(例如,如果id
是方法中的局部变量),那么您不必担心锁定/ etc ...即使您有匿名线程,也是如此方法,因为它们只能访问声明为final的局部变量。