34

JDK 的源码你真的读懂了吗?

 5 years ago
source link: https://mp.weixin.qq.com/s/QGI1wIB4NYZW8Gf-xBpl5Q?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如果看过JDK源码的同学基本上都看到过类似于下面的语句:

meqIzuV.png!web

对“final ReentrantLock lock = this.lock; ”这种写法不知道大家是啥感受,我当时看到是非常奇怪的,于是就搜索了一下,发现原作者对这种情况做了说明,原文如下:

eUvqMfn.jpg!web

其中第一句就提到了这样做的原因是:“ 归根究底是由于内存模型与OOP之间的原则不一致 ”,后面基本上都是对这句话做出说明。

要理解上面的内容必须要对Java的内存模型有所了解,Java的内存模型如下:

NVzeYzN.jpg!web

从上图我们可以知道Thread Stack 是以过程函数为访问对象,而不是以对象问访问的,线程栈内只有基本变量和指向对象的引用(对象本身是放在heap上)。

从java内存模型中可以看出,method只会存放对象引用(this指针),不会存放对象中的信息,只能再次通过this访问对象中的信息。

yiquAr3.jpg!web

所以这种写法,在访问lock的时候首先去访问this对象,然后获取lock的引用,最后再调用lock函数,每次访问lock中的函数都是这3步。

但是如果采用将字段赋值给局部变量在使用,之后就不需要访问this指针,少了一步操作. 也就是说this对象和其他普通对象在函数没有任何区别

UNRj6fv.jpg!web

为了验证,可以对代码进行反编译:

y6RrAv3.jpg!web

反编译的结果和内存模型推断出来的完全一致。 虽然采用将字段赋值给局部变量在以后使用中确实能够节省时间,但是目前的JDK版本对于这种情况下都做了优化。所以这种写法已经变成了 Doug Lea习惯了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK