科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Visual Basic.NET实现双检锁(DCL)模式

Visual Basic.NET实现双检锁(DCL)模式

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文介绍了称为双检锁模式的代码模式的工作原理及其在单例模式及多例模式中的应用

作者:阎宏博士 来源:天极网 2007年11月9日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
 关于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类图。


图2、一个Singleton类

  下面就是这个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类
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章