Java线程安全的单例模式

在Java并发编程实践(JAVA concurrency in practice)中的第十六章(Java存储模型)中.
有讲到对象安全发布.
其中就是以单例模式来说明这个安全初始化技巧的.这是学习分析总结如下:
[quote]
不正确发布带来的风险的真正原因是在"发布共享对象"与从"另一个线程访问它"之间,缺少happens-before排序.
[/quote]
不安全的发布.
发布(Publishing):
[quote]
发布(Publishing)一个对象的意思是使它能够被当前范围之处的代码所使用.比如将一个引用
存储到其他代码可以访问的地方.在一个非千私有的方法中返回这个引用,也可以把它传递到其他类的方法中.在很多情况下,我们需要确保对象及它们的内部状态不被暴露(publish).
[/quote]

代码清单1:不安全的惰性初始化:

public class UnsafeLazyInitialization{
private static Resource resource;
public static Resource getInstance(){
if(resource == null){
resource = new Resource();
}
return resource;
}
}


[quote]
除了不可变对象以外,使用被另一个线程初始化的对象,是不安全的,除非对象的发布是happens-before于对象的消费线程使用它.
[/quote]
安全初始化技巧:
代码清单2 线程安全的惰性初始化

public class SafeLazyInitialization{
private static Resource resource;
public synchronized static Resource getInstance(){
if(Resource == null){
resource = new Resource();
}
}
}



代码清单3 主动初始化

public class EagerInitialization{
private static Resource resource = new Resource();
public static Resource getResource() {
return resource;
}
}


像上面那样,使用主动的初始化,避免了每次调用SafeLazyInitialization的getInstance()的同步开销.这项技术可以和JVM的惰性类加载相结合,
创建一种惰性初始化技术,使得在通常的代码路径中都不需要同步.清单4的惰性初始化holder类技巧.使用一个专门用来初始化Resource的类.JVM将ResourceHolder的初始化被 延迟到真正使用它的时刻.因为Resource是在静态初始进行初始化的,所以不再需要额外的同步.,线程第一次调用getResource,引起ResourceHolder的加载和初始化,这个时候,正是静态初始阶段Resource完成初始化发生的时间.

清单4惰性初始化Holder类技巧

public class ResourceFactory{
private static ResourceHolder {
public static Resource resource = new Resource();
}
public static Resource getResource(){
return ResourceHolder.resource;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值