Java基础-基础语法-JVM执行自增运算的原理

Java工程师知识树 / Java基础

题目:下面代码执行后输入结果为?

public static void main(String[] args) {
    int ct = 0;
    for (int i = 0; i < 100; i++) {
        ct++;
    }
    System.out.println("ct:"+ct);

    int count = 0;
    for (int i = 0; i < 100; i++) {
        count = count++;
    }
    System.out.println("count:"+count);

    int size = 0;
    for (int i = 0; i < 100; i++) {
        size = ++size;
    }
    System.out.println("size:"+size);
}

答案为

ct:100
count:0
size:100

解析:

  • 1.通过ct与count,可以得到在java等语言中 count = count++ 与 count++ 是不等效的
  • 2.通过size与count,可以得到i++和++i的运行原理是不一样的

i++和++i的区别通过字节码查看一下

Java基础-基础语法-JVM执行自增运算的原理_第1张图片
image.png
public static void main(String[] args) {
    int count = 0;
    count = count++;
}

源代码解析出的字节码

public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1   // 把局部变量1的值放到栈顶,此时栈顶的值变为0
       3: iinc          1, 1     //局部变量1加1变为1,注意这时栈中仍然是0,没有改变
       6: istore_1  //把栈顶的值放到局部变量1中,即局部变量1这时候值还是0
       7: return
}
public static void main(String[] args) {
    int count = 0;
    count = ++count;
}

源代码解析出的字节码

public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iinc          1, 1    //局部变量1加1变为1,注意这时栈中仍然是0,没有改变
       5: iload_1   // 把局部变量1的值放到栈顶,此时栈顶的值变为1
       6: istore_1  //把栈顶的值放到局部变量1中,即局部变量1这时候由0变成了1
       7: return
}

上面题目答案解读:

count = count++;java虚拟机执行时是这样的: count的值加了1,但这时栈中的值还是0, 而后"="赋值操作又将栈中的值覆盖count,即count变成0,因此不管循环多少次,count都等于0。

而size = ++size; java虚拟机执行时是这样的: 栈中的值加了1,这时size的值还是0, 而后"="赋值操作将栈中的值覆盖size,即size变成1,完成一次循环后size值是加1的,所以执行完循环后,size值就是100了。

延伸问题:

可以通过哪些方式来保证并发安全的自增自减操作?

答:java 默认的自增自减运算符是非并发安全的,要想实现并发安全的自增自减操作可以通过如下几种方式实现:

  • 通过 synchronized 代码块或者方法来保证自增自减并发安全。
  • 通过主动使用 Lock 锁来保证自增自减并发安全。
  • 通过 JDK 提供的 AtomicInteger 类来直接保证自增自减并发安全。

上面几种做法中最推荐直接使用 AtomicInteger 的方式,因为其相对于其他几种方式封装性非常便捷,此外其实现基于 volatile 对象的 CAS 操作来保证并发安全,算是一种相对高效的方式。

你可能感兴趣的:(Java基础-基础语法-JVM执行自增运算的原理)