c中关于自增操作我测试了一小段代码:
int i = 0; int increment(){ int j = 0; return ++j; } void main(){ ++i; } ~ ~
i是全局变量,j是局部变量,反汇编出来的代码如下:
increment: pushl %ebp movl $1, %eax movl %esp, %ebp popl %ebp ret .size increment, .-increment .p2align 4,,15 .globl main .type main, @function main: pushl %ebp movl %esp, %ebp addl $1, i popl %ebp ret
可以看到关于自增运算的指令都是一条指令,加上一点限制:操作数是32位并且没有跨页,这是在C中;
下面看看java中:
public class increment{
public static int i = 0;
public static void main(String ar[]){
increment ic = new increment();
int j = 0;
ic.i++;
j++;
System.out.println(i+" "+j);
}
}
我这里同样设置了类变量和局部变量,下面是javap的部分结果:
7: astore_1 8: iconst_0 9: istore_2 10: aload_1 11: pop 12: getstatic #4; //Field i:I //开始的是对i的运算 15: iconst_1 16: iadd 17: putstatic #4; //Field i:I //i运算结束
20: iinc 2, 1 //j运算
可以看到java中对于局部变量和全局变量关于++操作的不一致,类变量的自增操作不是原子性的,通过getstatic ,iadd,putstatic 得出,是分别进行读,修改,写,而j的运算仅仅是一条iinc指令,局部变量是原子性的。。补充一下,不仅仅是类变量,实例变量(就算是没有声明static),它的自增操作也不是原子性的。
至于为什么java这么设计我想很简单吧,类的静态变量是所有实例进行共享,不是放在某一个方法栈中的,这个变量是这个类型的属性,对这个类变量的更改自然导致了所有实例的“状态”更改,而局部变量在方法返回之后是失去其作用域的。
友情链接:http://madbean.com/2003/mb2003-44/