关于Java原子性操作的【错误】理解(赋值和自增自减)
以下内容的错误之处
字节码并不是像其他原生程序构建产生的机器码一样,一条指令在CPU上就是执行一次,字节码需要JVM解析,一条字节码其实可能会对应多条CPU指令(具体取决于Java虚拟机的具体实现逻辑!!!),而原子操作要不一个操作可以在一条CPU指令执行完成,要不操作系统对这个操作做了处理,使其必须全部执行完毕,才能执行后续的其他操作。因此以下内容通过字节码来验证Java的原子性操作是完全错误的行为。
赋值操作是否是原子性?
不是,不管是基础数据类型还是引用数据类型,它都不是原子操作
【当然,如果以结果论的话,局部变量基本数据类型的赋值操作(long、double可能受到jvm、os等影响造成非原子性赋值),局部引用类型的null值赋值都是原子性的!】
int类型的赋值
booleanl类型的赋值,果然JVM是将boolean当成int来处理呢,ture是1,false是0
double类型的赋值
引用类型的赋值
由此可见,在Java中任何赋值操作都不是原子操作!它都具有先将被赋入的值加入到栈中,然后在赋值给变量。至于int a = b,这种方式的赋值则也不是原子操作,因为他需要先load b变量的值到栈中,然后在赋值给a,如下图所示:
int a = b操作
自增自减操作是否是原子性的?
只有局部变量的int类型,且自增自减的幅度在-32768 ~ 32767时,局部变量的int类型的自增自减操作都是通过iinc或iinc_w一条指令完成的,而其他数据类型则一定需要有压栈、运算、存回的操作。
局部变量int自增自减,幅度在-32768 ~ 32767
局部变量int自增自减,幅度超过-32768 ~ 32767
对象成员变量的自增自减操作
类变量的自增自减操作
byte的自增自减操作
其他就不一一举例了,都是大同小异。