java 多线程内存模型_java 内存模型、多线程

经典j2ee设计模式Double-Checked

Locking失效问题

双重检查锁定失效问题,一直是JMM无法避免的缺陷之一.了解DCL失效问题,

可以帮助我们深入JMM运行原理.

要展示DCL失效问题,

首先要理解一个重要概念- 延迟加载(lazy loading).

非单例的单线程延迟加载示例:

class Foo

{

private Resource res = null;

public Resource getResource()

{

//

普通的延迟加载

if (res == null)

res = new Resource();

return res;

}

}

非单例的 多线程延迟加载示例:

Class Foo

{

Private Resource res = null;

Public

synchronized

Resource getResource()

{

//

获取实例操作使用同步方式

,

性能不高

If

(res == null) res = new Resource();

return

res;

}

}

非单例的 DCL多线程延迟加载示例:

Class Foo

{

Private

Resource res = null;

Public

Resource getResource()

{

If

(res == null)

{

//

只有在第一次初始化时

,

才使用同步方式

.

synchronized(this)

{

if(res

== null)

{

res

= new Resource();

}

}

}

return

res;

}

}

Double-Checked

Locking看起来是非常完美的。但是很遗憾,根据Java的语言规范,上面的代码是不可靠的。

出现上述问题, 最重要的2个原因如下:

1, 编译器优化了程序指令,

以加快cpu处理速度.

2, 多核cpu动态调整指令顺序,

以加快并行运算能力.

问题出现的顺序:

1, 线程A, 发现对象未实例化,

准备开始实例化

2, 由于编译器优化了程序指令,

允许对象在构造函数未调用完前, 将 共享变量的引用指向 部分构造的对象, 虽然对象未完全实例化, 但已经不为null了.

3, 线程B,

发现部分构造的对象已不是null, 则直接返回了该对象.

不过, 一些著名的开源框架,

包括jive,lenya等也都在使用DCL模式, 且未见一些极端异常.

说明,

DCL失效问题的出现率还是比较低的.

接下来就是性能与稳定之间的选择了?

DCL的替代 Initialize-On-Demand

:

public class Foo {

//

似有静态内部类

,

只有当有引用时

,

该类才会被装载

private static class LazyFoo {

public static Foo foo = new Foo();

}

public static Foo getInstance() {

return LazyFoo.foo;

}

}

维基百科的DCL解释:

DCL的完美解决方案:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值