美文网首页Java工程师知识树
Java基础-基础语法-JVM执行自增运算的原理

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

作者: HughJin | 来源:发表于2020-12-17 07:04 被阅读0次

    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的区别通过字节码查看一下

    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执行自增运算的原理

        本文链接:https://www.haomeiwen.com/subject/rxowgktx.html