增量运作机制

时间:2012-11-15 12:24:07

标签: java variable-assignment atomic

正如许多开发人员所知,增量运算符不是原子的。

例如:

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个步骤而不是另一个?

2 个答案:

答案 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 + 1id变量的先前设定值会带来新的id值,如果您遇到竞争条件,id的结束值可能不是您所期望的

一些注意事项:

  • 如果要从多个线程设置id变量,无论您如何设置它,都需要同步它。总是,或者根本不设置值(参见Java Concurrency in Practice的第3章)。或者,您可以将id变量设为volatile;
  • 这只有在实际可以从多个线程访问id时才有意义。如果不是这种情况(例如,如果id是方法中的局部变量),那么您不必担心锁定/ etc ...即使您有匿名线程,也是如此方法,因为它们只能访问声明为final的局部变量。