JDK源码笔记之Integer深度解析以及并发下错误的加锁方式踩坑笔记

Posted 不清不慎的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK源码笔记之Integer深度解析以及并发下错误的加锁方式踩坑笔记相关的知识,希望对你有一定的参考价值。

对于Java的数据类型Integer,大多人认为不就很简单的一个数据类型吗?是的,我以前也不在意,感觉关于integer没什么可说,但是不深入源码你永远不知道它给你留下的坑。 ------------------------------------------------------------------------**一、谈谈integer留下的坑**

首先我们来看一段代码。

package cn.shinelon.jvm;public class TestInteger {    public static void main(String[] args) {        Integer i1=1;        Integer i2=1;        System.out.println(i1==i2);        Integer i3=129;        Integer i4=129;        System.out.println(i3==i4);    } }

上面的代码只要接触过Java的人都能够看明白,不用过多解释,比较两个integer变量是否相等。估计一眼就可以看出答案,但是对不对呢?可能与大多人所预料的结果大相径庭,大多人觉得两个结果输出一定都是true,但是我们来看看运行结果。



这个结果着实让很多大吃一惊,为什么第二个会是false呢,i3和i4不都是129吗?怎么不相等了,下面来让我们看看这其中的原因:使用javap -c命令反编译class文件:

JDK源码笔记之Integer深度解析以及并发下错误的加锁方式【踩坑笔记】


我们可以看到Integer i1,i2,i3,i4这些语句都调用了Integer.valueOf()方法,因此,我们来看看valueOf()方法的源码。


package cn.shinelon.jvm;public class TestInteger {    public static void main(String[] args) {        Integer i1=1;        Integer i2=1;        System.out.println(i1==i2);        Integer i3=129;        Integer i4=129;        System.out.println(i3==i4);    } }

对于上面这段代码运行结果,这里就不卖关子了,理论情况下很多人看上去认为结果是20000,但是事实不是这样,结果会等到一个比20000小很多的数,比如12698,这是为什么呢?我们可以按照上面的方式使用javap命令反编译run()方法里面的代码,发现它任然调用了valueof方法,这就很好解释了,因为在该方法里它会在超出缓冲区范围后new一个新的对象,也就是说synchronized关键字加在两把不同的锁上面,因此两个线程不能同步,所以结果会比20000小很多。怎么解决以上的问题呢?很简单,只需要将上面代码改为synchronized(instance)即可。上面是个人对Integer的一些小小的总结以及解读,如有不足之处还请指教!

以上是关于JDK源码笔记之Integer深度解析以及并发下错误的加锁方式踩坑笔记的主要内容,如果未能解决你的问题,请参考以下文章

HashMap并发下死循环问题解析

HashMap源码深度解析(深入至红黑树实现)以及与JDK7的区别四万字

JDK:java.lang.Integer源码解析

深度学习框架之Caffe源码解析

Integer.parseInt不同jdk源码解析

GitHub上连夜被下架!阿里巴巴2021版JDK源码笔记(2月第三版)