一道JAVA面试题却难倒了超过一半的程序员

小邹最近看到了一道题,听说是某人阿里面试的时候做过,印象非常深刻的题目,下面直接上题:

一道JAVA面试题却难倒了超过一半的程序员

期待的运行结果:

i=1
i=2
i=4
i=3
...
..
i=100

无序输出 i=1到1=100。可惜,这是错误的答案。

实际运行结果中,可能出现部分值没有被输出,部分值被重复输出,如下:

i = 2
i = 2
i = 3
...
i = 100

这里仅列举了一种,你可以自己尝试运行几次。

原因分析

代码中 i 变量,是一个Integer对象,当代码中两个线程执行 i++时,

实际运行时的 i++ 的实现逻辑是这样的:

i = Integer.valueOf(i.intValue() + 1);

而Integer.valueOf每次是返回一个新的Integer对象,所以,我们的synchronized实际上没有起到你预想中的效果。

我是如何发现这个实现内幕的呢?

底层原理分析

1、 分析编译后的MyRunnable.class文件,发现 i++ 在虚拟机中的执行原理。

通过jdk自带的javap命令工具,对MyRunnable.class 进行分析

javap -v MyRunnable.class

可以看到输出内容中(如下图),JVM执行 i++ 的内部逻辑。

使用javap命令分析class的结果截图

一道JAVA面试题却难倒了超过一半的程序员

这个逻辑,通过代码表达出来就是这句“i = Integer.valueOf(i.intValue() + 1);

2、 查看Integer的源码,当变量i的值发生变化后,发现 Integer.valueOf 每次都是新对象。

/** Integer源码取自jdk1.8 */
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}


分享到:


相關文章: