考试网 >> IT认证 >> JAVA >> JAVA指导 >> Java 线程/内存模型的缺陷和增强

Java 线程/内存模型的缺陷和增强

发布时间:2006-06-28 10:50     点击:
分页:上一页  1 2 [3] 4 5 6  下一页

这种看起来很完美的优化技巧就是Double-Checked Locking。但是很遗憾,根据Java的语言规范,上面的代码是不可靠的。

造成DCL失效的原因之一是编译器的优化会调整代码的次序。只要是在单个线程情况下执行结果是正确的,就可以认为编译器这样的“自作主张的调整代码次序”的行为是合法的。JLS在某些方面的规定比较自由,就是为了让JVM有更多余地进行代码优化以提高执行效率。而现在的CPU大多使用超流水线技术来加快代码执行速度,针对这样的CPU,编译器采取的代码优化的方法之一就是在调整某些代码的次序,尽可能保证在程序执行的时候不要让CPU的指令流水线断流,从而提高程序的执行速度。正是这样的代码调整会导致DCL的失效。为了进一步证明这个问题,引用一下《DCL Broken Declaration》文章中的例子:

设一行Java代码:

Objects[i].reference = new Object();

经过Symantec JIT编译器编译过以后,最终会变成如下汇编码在机器中执行:

0206106A mov eax,0F97E78h0206106F call 01F6B210 ;为Object申请内存空间 ; 返回值放在eax中02061074 mov dword ptr [ebp],eax ; EBP 中是objects[i].reference的地址 ; 将返回的空间地址放入其中 ; 此时Object尚未初始化02061077 mov ecx,dword ptr [eax] ; dereference eax所指向的内容 ; 获得新创建对象的起始地址02061079 mov dword ptr [ecx],100h ; 下面4行是内联的构造函数0206107F mov dword ptr [ecx+4],200h 02061086 mov dword ptr [ecx+8],400h0206108D mov dword ptr [ecx+0Ch],0F84030h

可见,Object构造函数尚未调用,但是已经能够通过objects[i].reference获得Object对象实例的引用。

如果把代码放到多线程环境下运行,某线程在执行到该行代码的时候JVM或者操作系统进行了一次线程切换,其他线程显然会发现msg对象已经不为空,导致Lazy load的判断语句if(objects[i].reference == null)不成立。线程认为对象已经建立成功,随之可能会使用对象的成员变量或者调用该对象实例的方法,最终导致不可预测的错误。

结合代码3来举例说明,假设Resource类的实现如下:

Class Resource{ Object obj;}

即Resource类有一个obj成员变量引用了Object的一个实例。假设2条线程在运行,其状态用如下简化图表示:
分页:上一页  1 2 [3] 4 5 6  下一页
版权申明:未经书面授权请勿转载本站信息!!作品版权归所属媒体与作者所有!!
发表评论: 匿名发表 用户名: 查看评论
您将承担一切因您的行为、言论而直接或间接导致的民事或刑事法律责任
留言板管理人员有权保留或删除其管辖留言中的任意内容
本站提醒:不要进行人身攻击。谢谢配合。
在本站搜索相关信息
2003-2005 Ksw123.com All Rights Reserved. - TOP
Copyright © 2006 Ksw123.com. All rights reserved.中国考题网 版权所有