关于dcl模式的讨论
第一次接触到这个技巧的读者必定会有很多问题,诸如第一次检查或者第二次检查可不可以省掉等等。回答是,按照多线程的原理和dcl模式的预想方案,它们是不可以省掉的。
首先,如果省略了第一次检查,那么工厂方法就变成下面这样:
public shared function getinstance() as product
thread.sleep(10)
'位置1
'位置2
m.waitone()
'位置3
if (instance is nothing) then '位置4
instance = new product()
end if
m.releasemutex()
return instance
end function
代码清单7、省略了第一重检查的线程安全的工厂方法
这就造成不论产品实例是否存在都会在位置2等待的情况,也就是等于没有优化前的线程安全的工厂方法(参见代码清单5),虽然并没有错误地产生多于一个的产品对象,但也没有达到优化的目的。
其次,如果省略了第二重检查的话,工厂方法模式就会变成下面这样:
if (instance is nothing) then '位置1
'位置2
m.waitone()
'位置3
instance = new product()
m.releasemutex()
end if
return instance
代码清单8、省略了第二重检查的线程安全的工厂方法
这是否可以呢?同样假设线程a和b作为第一批调用者同时或几乎同时调用静态工厂方法。
1. 因为线程a和b是第一批调用者,因此当它们进入此静态工厂方法时,instance变量是nothing。因此线程a和b会同时或几乎同时到达位置1。
2. 假设线程a会首先到达位置2,并进入m.waitone()而到达位置3。这时,由于m.waitone()的同步化限制,线程b无法到达位置3,而只能在位置2等候。
3. 线程a执行instance = new product()语句,使得instance变量得到一个值,即对一个product对象的引用。此时,线程b只能继续在位置2等候。
4. 线程a退出m.waitone(),返回instance对象,退出静态工厂方法。
5. 线程b进入m.waitone()块,达到位置3,线程b执行instance = new product()语句,使得instance变量得到一个新值,b退出静态工厂方法。
因此线程a和b创建了两个产品类的实例。换言之,没有第二重检查是不可以的。
dcl模式在singleton模式中的应用
singleton模式描述的是只有一个实例的类,这个类叫做singleton类。singleton类自己向外界提供自己的唯一实例。一般情况下,singleton模式多使用在多线程环境中,这使得线程同步化变得非常重要。
根据singleton类的实例创建方式的不同,singleton模式的实现可以分成两种:"饿汉式"和"懒汉式"。"懒汉式"singleton模式会在工厂方法被调用的时候判断是否需要创建产品的实例:如果实例已经存在了,就直接返还这个实例,反之就首先创建一个实例,再存储起来,然后返还这个实例。
熟悉singleton模式的读者应该可以注意到,dcl模式可以使用到"懒汉式"的singleton模式中。实际上,singleton类就是dcl模式的特殊情况,只要把工厂类与产品类合并就可以得到singleton类。请参见下面的uml类图。
下面就是这个singleton类的源代码:
public class singleton
private shared instance as singleton
private shared m as mutex = new mutex()
public sub new()
system.console.writeline("singleton object is created.")
end sub
public shared function getinstance() as singleton
thread.sleep(10)
if instance is nothing then
m.waitone()
if instance is nothing then
instance = new singleton()
end if
m.releasemutex()
end if
return instance
end function
end class
代码清单9、二重检查的线程安全的singleton类
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器