java中的single_java中的double-checked locking

在java中使用单例的类时,最简单的方法可以是:

public Class Singletin{

private static Singletin

instance = new Singletin();

public static Singletin

getInstance(){

return instance;

}

}

但是为了使用延迟初始化(不需要在应用启动时就初始化Singletin的instance变量,只是在第一次使用时初始化),经常看看到使用如下的方法:

public Class Singletin{

private static Singletin

instance = null;

public static Singletin

getInstance(){

if(instance == null){

synchronized (Singletin.class){

if(instance ==

null){ instance = new Singletin();

}

}

}

return instance;

}

}

看起来这是一个不错的方法,但是实际上呢?让我们来看看java的内存模型

在多线程环境中,每一个线程有自己的本地内存(local memory),

synchronized进行的操作并不仅仅是用信号量机制进行加锁,还促使线程的本地内存和主内存进行数据同步memory

barrier -- a forced synchronization between the thread's local

memory and main

memory.:进入synchronized区域时,把主内存的变量值读入本地内存,而退出synchronized区域时,把本地内存的变量值写入主

内存。

instance = new Singletin();执行的操作有三步:分配内存,

调用构造函数初始化(初始化各个属性),instance指向分配的内存。但是这个顺序不是固定的,有可能是:分配内存,

instance指向分配的内存,调用构造函数初始化(初始化各个属性)。如果在执行到第二步后,另外一个线程进入getInstance函数,首先判断

instance!=null,则直接返回该没有初始化的内存对象,后续的使用就会产生问题。可能有人会说不是退出synchronized的时候才会进

行数据同步吗?这样就不会产生刚刚分配内存,还没有初始化的问题。但是进行数据同步也不是原子的操作,也会同样存在问题。另外由于处理器对内存的

cache也回存在问题。总之导致产生double-checked

locking的问题很多,因此很多方法对某一种情况可以避免,但是对另一种情况就不能避免。

在jdk5之后(包含JDK5)之后,可以使用volatile限制来定义instance,能够避免double-checked

locking.

public Class Singletin{

private volatile static

Singletin instance = null;

public static Singletin

getInstance(){

if(instance == null){

synchronized (Singletin.class){

if(instance ==

null){ instance = new Singletin();

}

}

}

return instance;

}

}

另外一篇很好的分析文章:

http://blog.csdn.net/ralph623/article/details/471026

http://www.blogjava.net/Jhonney/archive/2011/04/08/110280.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值