0

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

例如:

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

4

2 回答 2

2

什么概念迫使编译器将第一个转换为 3 个步骤而不是另一个?

不是,id = xyz + 1会编译成如下字节码:

 7  iload_2 [xyz]
 8  iconst_1
 9  iadd
10  istore_1 [id]

从字节码不难看出,上面不是“一步到位”

于 2012-11-15T12:35:28.537 回答
1

没有什么可以说的:

id = anotherVariable + 1

不会分三步执行。但是无论你运行上面的代码多少次,最终的结果总是一样的(变量的值id总是anotherIntVariable加 1),就像在例子中一样id = id + 1,之前在变量上设置的值id驱动新id值,如果您遇到竞争条件,最终值id可能不是您所期望的。

几点注意事项:

  • 如果你是id从多个线程设置变量,那么无论你如何设置它,你都需要同步它。总是,否则可能根本不会设置该值(请参阅 Java 并发实践的第 3 章)。或者,您可以将id变量设置为 volatile;
  • id这仅在实际上可以从多个线程访问时才重要。如果不是这种情况(例如,如果id是方法中的局部变量),那么您无需担心锁定/等...即使您在方法中有匿名线程也是如此,因为它们只能访问声明为 final 的局部变量。
于 2012-11-15T12:35:21.770 回答