单例模式《漫谈设计模式》阅读笔记

单例模式:

如果要保证系统里一个类最多只能存在一个实例时,我们就需要用单例模式。这种情况在我们应用中经常碰到,例如缓存池,数据库连接池,线程池,一些应用服务实例等。

 

最简单的单例:

Public class Singleton{

Private static Singleton instance = new Singleton();

 

Private Singleton();

 

Public static Singleton getInstance(){

Return instance;

}

}

此实现是线程安全的,使用也非常简单:Singleton singleton=Singleton.getInstance();

 

延迟创建:

Public class UnTreadSafeSingleton{

Private static Singleton instance = new Singleton();

 

Private Singleton();

 

Public static UnTreadSafeSingleton getInstance(){

if(instance==null){

Instance=new UnTreadSafeSingleton();

}

return instance;

}

}

上述实现不是线程安全的,为了达到线程安全可以在获取实例的方法上加上关键字synchroniezd。但是在多线程高并发访问的情况下,给方法加上synchroniezd关键字会使性能大不如前。我们仔细分析一下不难发现,使用synchroniezd关键字对整个getInstance()方法进行同步是没有必要的:我们只要保证实例化这个对象的那段代码被一个线程执行就可以了,而返回引用的那段代码是木有必要同步的。按照这个想法,大致代码如下:

Public class DoubleCheckSingleton{

Private volatile static DoubleCheckSingleton instance=null;

//constructors

Public static DoubleCheckSingleton getInstance(){

if(instance==null){

Synchronized(DoubleCheckSingleton.class){

if(instance==null)

Instance=new DoubleCheckSingleton();

}

}

return instance;

}

}

getInstance()方法里,我们首先判断此实例是否已经被创建,如果还没有创建,首先使用synchronized同步实例化代码块。在同步代码块里,我们还需要再次检查是否已经创建了此类的实例,这是因为:如果没有第二次检查,这时有两个线程AB同时进入该方法,它们都监测到instancenull,不管哪一个线程先占据同步锁创建实例,都不会阻止另一个线程继续进入实例化代码重新创建实例对象。

属性instance是被volatile修饰的,因为volatile具有synchroniezd的可见性特点,也就是说线程能够自动发现volatile变量的最新值。这样,如果instance实例化成功,其他线程便能立即发现。

posted @ 2012-01-15 18:25  rason2008  阅读(228)  评论(1编辑  收藏  举报