工具软件   办公软件   操作系统   网络安全   设计在线   程序开发   教程宝典   软件下载   软件论坛
您的位置:软件 > 开发者网络 > 微软开发专栏 > Visual Studio.net专栏 > VB.net > 正文
Visual Basic.NET实现双检锁(DCL)模式
[文章信息]
作者:阎宏博士
时间:2005-02-26
出处:天极网
责任编辑:方舟
[文章导读]
本文介绍了称为双检锁模式的代码模式的工作原理及其在单例模式及多例模式中的应用
advertisement
热点推荐
· 动画图解:Word表格自动套用格式
· 游戏开发新手入门之Win32程序资源
· VB中使用DDE技术为应用程序增辉
· Java新手留意:Java编程三十条规则
· 设计欣赏:《夜精灵》之守望
[正文]

1 2 3 4  下一页

  本文介绍了称为双检锁(Double-Check Locking简称DCL)模式的代码模式,它的工作原理及其在Singleton(单例)模式及Multiton(多例)模式中的应用,并且讨论了DCL模式在Visual Basic.NET和C#语言中的实现。其中Visual Basic.NET的源代码可以在文中看到,C#的源代码在附录中给出。

  本文假设读者熟悉Visual Basic.NET或C#的多线程概念、设计模式的基本概念,以及UML基本图标。

  DCL模式(Double-Check Locking Pattern)有时又称作双检模式(Double-Check Pattern),只有在多线程的环境中才有用。它是从C语言移植过来的。在C语言里,DCL模式常常用在多线程环境中类的迟实例化(Late Instantiation)里。

  DCL模式通常与Factory模式一同使用,用来循环使用产品对象。如果读者熟悉Singleton(Singleton)模式的话,DCL模式可以使用到"懒汉式"的Singleton模式里面,用来提供唯一的产品对象。通过进一步推广,可以使用到Multiton模式和Flyweight模式里面。

  从Factory模式谈起

  为了解释什么是DCL模式,还是从Factory模式谈起吧。

  在下面的类图中,工厂类Factory0有一个共享方法GetInstance()用来提供产品类Product的实例。


图1、一个由工厂类与产品类组成的系统。

  Factory0的源代码如下:

Public Class Factory0
 Public Shared Function GetInstance() As Product
  Return New Product()
 End Function
End Class
代码清单1、Factory0类的源代码

  显然,只要调用GetInstance()方法就会得到Product类的实例,每一次调用得到的都是新的实例。Product类特别提供了计数的方法,通过调用GetCount()方法就可以得到Product所有实例的总数。

Public Class Product
Private Shared count As Integer = 0

Public Sub New()
 count += 1
 System.Console.WriteLine("Product number {0} is created.", count)
End Sub

Public Shared Function GetCount() As Integer
 Return count
 End Function
End Class
代码清单2、产品类Product的源代码

  但是如果产品类的实例必须循环使用,而不能无限制创建的话,工厂方法GetInstance()的内容必须改写,以实现必要的循环逻辑。而最简单的循环逻辑,就是重复使用单一的产品类实例。比如下面的源代码就实现了单一产品类实例的逻辑:

Public Class Factory1
Private Shared instance As Product

Public Shared Function GetInstance() As Product
 If (instance Is Nothing) Then
  instance = New Product()
 End If
 Return instance
End Function
End Class
代码清单3、工厂类Factory1的源代码

  简单得不能再简单了吧?如果已经创建过Product类实例的话,就返还这个实例;反之,就首先创建这个实例,将之记录在案,然后再返还它。

  写出这样的代码,本意显然是要保持在整个系统里只有一个Product 的实例;因此才会有 If (instance Is Nothing) Then 的检查。不很明显的是,如果在多线程的环境中运行,上面的代码会有两个甚至两个以上的Product对象被创建出来,从而造成错误。

  在多线程环境里,如果有两个线程A和B几乎同时到达 If (instance Is Nothing) Then语句的外面的话,假设线程A比线程B早一点点,那么:

  1. A会首先进入If (instance Is Nothing) Then 块的内部,并开始执行New Product()语句。 至此时,instance变量仍然是Nothing,直到线程A的New Product()语句返回并给instance变量赋值。

  2. 但是,线程B并不会在If (instance Is Nothing) Then 语句的外面等待,因为此时instance Is Nothing是成立的,它会马上进入If (instance Is Nothing) Then语句块的内部。 这样,线程B会不可避免地执行instance = New Product()的语句,从而创建出第二个实例来。

  3. 下面,线程A的instance = New Product()语句执行完毕,instance变量得到了真实的对象引用, (instance Is Nothing)不再为真。第三个线程不会在进入If (instance Is Nothing) Then语句块的内部了。

  4. 紧接着,线程B的instance = New Product()语句也执行完毕,instance变量的值被覆盖。但是第一个Product对象被线程A引用的事实不会改变。

  这时,线程A和B各自拥有一个独立的Product对象,而这是错误的。为了能够直观地看到程序执行的结果,可以运行下面的客户端代码:

Private Sub Run1()
 Dim o As Product
 o = Factory1.GetInstance
 System.Console.WriteLine("Total number of objects created: {0} ", o.GetCount)
End Sub

Private Sub btnCreate1_Click(…) Handles btnCreate1.Click
 Dim t(9) As Thread
 Dim count As Integer

 For count = 0 To 9
  t(count) = New Thread(AddressOf Run1)
  t(count).Start()
 Next
End Sub
代码清单4、客户端的源代码

  另外在Factory1的GetInstance()方法的第一行加入:

Thread.Sleep(10)

  的语句,相当于模拟一个冗长的产品创建过程,使得最早进入的线程等待后面的线程,从而凸显现多线程的问题。

  上面的客户端代码使用了10个线程同时调用工厂方法,然后调用产品的计数方法,打印出产品类的实例总数。如果读者运行一下这些代码的话,就会发现,工厂方法会创建出远多于1个的产品实例,在笔者运行这段代码时,系统整整产生了9个产品实例。

  因此Factory1作为循环使用产品实例的工厂在多线程环境中是失败的。使用类似于代码清单4的客户端进行试验的话,可以看出系统自始至终仅仅创建了一个产品实例。


1 2 3 4  下一页

发表评论推荐给朋友我想参加相关培训打印我对此感兴趣订阅电子杂志
相关内容焦点新闻
  • 浅议Visual Basic.NET中HOOK的应用
  • 用VB.NET结合Excel设计统计生产报表
  • VB.NET上传图片并在DataGrid中显示
  • Visual Stuido.NET扩展存储过程
  • 用VB.net实现Smartphone中进程启动
  • 无需再购新浪股票 传盛大已总体控股新浪36%
  • 微软否认XP优惠遭冷遇 开始发放电子优惠券
  • 电盈网通公布中国业务发展计划 合作四大块
  • 中关村在线前员工将老东家告上法庭
  • EVD获2500台销售“大单” 市场普及做好准备
  • 新浪首次正式表态 反对盛大控制可以和谈
  • 财富"最受推崇公司"出炉 戴尔微软挤进前四
  • 盛大急切收购新浪 因为看中新浪3D游戏?
  • Advertisement

    天极无线


    奇妙科幻|美好风光|清风车影|漫画卡通|星座生肖|明星写真|动物世界
    老鼠爱大米
    挥着翅膀的女孩
    女人味
    栀子花开
    白月光
    刚刚好
    江南
    快乐崇拜
    亲爱的你怎么不在我身边
    小薇
    2002年的第一场雪
    有多少爱可以重来
    我的地盘
    七里香
    情人
     
    老鼠爱大米 老板电话
    冲动的惩罚 七里香
    我不是黄蓉 女生撒娇
    盛夏的果实 坚持到底
    孤单北半球 眉飞色舞
    挪威的森林 可爱女人
    最浪漫的事 老板电话

    CSEEK搜索