- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
有关双检测锁定DCL和Singleton模式的问题 看OOP教材时,提到了一个双检测锁定(Double-Checked Lock, DCL)的问题,但是书上没有多介绍,只是说这是一个和底层内存机制有关的漏洞。查阅了下相关资料,对这个问题大致有了点了解。 从头开始说吧。 在多线程的情况下Singleton模式会遇到不少问题,一个简单的例子 1: class Singleton { 2: private static Singleton instance = null; 3: 4: public static Singleton instance() { 5: if (instance == null) { 6: instance = new Singleton(); 7: } 8: return instance; 9: } 10: } 假设这样一个场景,有两个线程调用Singleton.instance(),首先线程一判断instance是否等于null,判断完后一瞬间虚拟机把线程二调度为运行线程,线程二再次判断instance是否为null,然后创建一个Singleton实例,线程二的时间片用完后,线程一被唤醒,接下来它执行的代码依然是instance = new Singleton(); 两次调用返回了不同的对象,出现问题了。 最简单的方法自然是在类被载入时就初始化这个对象:private static Singleton instance = new Singleton(); JLS(Java Language Specification)中规定了一个类只会被初始化一次,所以这样做肯定是没问题的。 但是如果要实现延迟初始化(Lazy initialization),比如这个实例初始化时的参数要在运行期才能确定,应该怎么做呢? 依然有最简单的方法:使用synchronized关键字修饰初始化方法: 1.public synchronized static Singleton instance() { 2. if (instance == null) { 3. instance = new Singleton(); 4. } 5. return instance; 6.} 这里有一个性能问题:多个线程同时访问这个方法时,会因为同步而导致每次只有一个线程运行,影响程序性能。而事实上初始化完毕后只需要简单的返回instance的引用就行了。 双检测锁定解决方案 DCL是一个“看似”有效的解决方法,先把对应代码放上来吧: 1 : class Singleton { 2 : private static Singleton instance = null ; 3 : 4 : public static Singleton instance() { 5 : if (instance == null ) { 6 : synchronized (this) { 7 : if (instance == null) 8 : instance = new Singleton(); 9 : } 10 : } 11 : return instance; 12 : } 13 : } 用JavaWorld上对应文章的标题来评论这种做法就是smart, but broken。来看原因: Java编译器为了提高程序性能会进行指令调度,CPU在执行指令时同样出于性能会乱序执行(至少现在用的大多数通用处理器都是out-of-order的),另外cache的存在也会改变数据回写内存时的顺序[2]。JMM(Java Memory Model, 见[1])指出所有的这些优化都是允许的,只要运行结果和严格按顺序执行所得的结果一样即可。 Java假设每个线程都跑在自己的处理器上,享有自己的内存,和共享的主存交互。注意即使在单核上这种模型也是有意义的,考虑到cache和寄存器会保存部分临时变量。理论上每个线程修改自己的内存后,必须立即更新对应的主存内容。但是Java设计师们认为这种约束会影响程序性能,他们试着创造了一套让程序跑得更
您可能关注的文档
最近下载
- 新人教版高中数学必修第二册统计全套课件.pptx VIP
- 台球厅消防安全应急预案.docx VIP
- 海外代理协议合同协议.docx VIP
- 初中教科研课题:《初中语文预习方法研究》课题研究工作报告.doc VIP
- 2025至2030年中国新疆维吾尔自治区建筑市场运行态势及行业发展前景预测报告.docx
- 简述10KV 高压配电柜安装.doc VIP
- GB50148-2010 电气装置安装工程电力变压器油浸电抗器、互感器施工及验收规范.pdf VIP
- 2025航天恒星科技有限公司招聘80+人笔试历年参考题库附带答案详解.pdf
- RB∕T 174-2021 司法鉴定法庭科学机构能力专业要求.pdf
- CP-717安装指南.doc VIP
文档评论(0)