首页  学校文化  作品展示  咨询留言  课程介绍  招聘求职  权威认证  精彩教程
咨询留言
在线报名
对外事业
您当前的位置:长城教育网 >> 精彩教程 >> 编程开发 >> 正文
长城学校暑期八折优惠招生 长城学校大专学历、中专学历证书班招生-学历网上可查 长城学校对外事业部承揽业务
Visual Basic.NET实现双检锁(DCL)模式(二)
作者:长城学校     来源:长城教育网     点击数:     更新时间:2006-8-24   
  文章导读:
长城计算机学校报名咨询:0315-7759907 就业中心:0315-2625172 电脑硬件:0315-2657607 网站开发:0315-2931022 装修设计:0315-2678275 电子邮箱:ccjyw@263.net 咨询QQ:412644056 工作时间:周一至周六8:00-21:00;周日:8:00-18:00
导读广告

算机学校 唐山电脑学校 唐山计算机学校

正文:

一个线程安全的版本

  为了克服没有线程安全的缺点,下面给出一个线程安全的GetInstance()方法:

<MethodImpl(MethodImplOptions.Synchronized)>_
Public Shared Function GetInstance() As Product
 Thread.Sleep(10)

 If (instance Is Nothing) Then
  instance = New Product()
 End If

 Return instance
End Function
代码清单5、这是一个线程安全的正确答案

  显然,由于整个静态工厂方法都是同步化的,因此,不会有两个线程同时进入这个方法。因此,当线程A和B作为第一批调用者同时或几乎同时调用此方法时:

  早到一点的线程A会率先进入此方法,同时线程B会在方法外部等待;

  1. 对线程A来说,instance变量的值是Nothing,因此instance = New Product()语句会被执行。

  2. 线程A结束对方法的执行,instance变量的值不再是Nothing。

  3. 线程B进入此方法,instance变量的值不再是Nothing,因此instance = New Product()语句不会被执行。线程B取到的是instance变量所含有的引用,也就是对线程A所创立的Product实例的引用。

  显然,线程A和B持有同一个Product实例,这是正确的。

  读到这里,读者可以参看本文后面的问答题1、2和3。

  优化的线程安全版本---DCL模式

  再进入本节的讨论之前,首先复习一下Mutex类。Mutex可以提供排他性的访问限制,通过只允许一个线程访问这个资源,从而达到同步化的目的。需要取得访问许可的线程,必须调用WaitOne()方法。如果当前没有其他线程访问,则线程可以取得访问许可;不然就会在这个语句处等待。访问结束的时候,可以调用ReleaseMutex()方法,释放访问许可。

  仔细审察上面的代码清单5就会发现,同步化实际上只在instance变量第一次被赋值之前才有用。在instance变量有了值以后,同步化实际上变成了一个不必要的瓶颈。如果能有一个方法去掉这个小小的额外开销,不是更加完美了吗?因此,就有了下面这个设计巧妙的双检锁(Double-Check Locking)。

Public Class Factory3
Private Shared instance As Product
Private Shared m As Mutex = New Mutex()

Private Sub New()
 System.Console.WriteLine("Factory object is created.")
End Sub

Public Shared Function GetInstance() As Product
 Thread.Sleep(10)
 If (instance Is Nothing) Then '位置1
  '位置2
  m.WaitOne()
  '位置3
  If (instance Is Nothing) Then '位置4
   instance = New Product()
  End If
  m.ReleaseMutex()
 End If

 Return instance
 End Function
End Class
代码清单6、使用DCL模式的懒汉式工厂类

  对于初次接触DCL模式的读者来说,这个技巧的思路并不明显易懂,因此本文在这里给出一个详尽的解释。同样,这里假设线程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,进而达到位置4。由于instance变量已经不是Nothing了,因此线程B退出 m.WaitOne(),返回instance所引用的Product对象(也就是线程A所创建的Product对象),退出静态工厂方法。

  到此为止,线程A和线程B得到了同一个Product对象。可以看到,在上面的方法GetInstance ()中,同步化仅用来避免多个线程同时初始化这个类,而不是同时调用这个静态工厂方法。如果这是正确的,那么使用这一个模式之后,"懒汉式"工厂类就可以摆脱掉同步化瓶颈,达到一个完美的境界。这就是DCL模式。

长城计学校 长城教育版权所有 唐山电脑学校 唐山计算机学校

  文章录入:长城学校
  • 上一篇文章: Visual Basic.NET实现双检锁(DCL)模式

  • 下一篇文章: 没有了
  • 我要咨询   我要报名   打印此文  关闭窗口
    热门文章
    推荐文章
    相关文章
    Visual Basic.NET实现双检锁(DCL...
    用Excel函数快速录入26个英文字母...
    Office超级技巧之PowerPoint(下...
    Office超级技巧之PowerPoint(上...
    PowerPoint中制作倒影艺术字
    PowerPoint制作自动交互问答课件...
    巧用PowerPoint制作比赛计时器
    微软Office Powerpoint制作技巧四...
     普通 怎样制作刻录系统自动还原光碟
     普通 学好五笔字型输入法的几点建议
     普通 输入法使用诀窍
     普通 广告策划书的书写
     普通 用 gdb 调试 GCC 程序
     普通 C 语言编程——什么是C
     普通 硬盘故障巧维修——了解常见的硬...
     普通 硬盘故障巧维修——为什么BIOS检...
     推荐 Adobe InDesign CS 简介
     推荐 电脑艺术设计大师之路#7-图像调...
     推荐 电脑艺术设计大师之路#6-图像调...
     推荐 3DS Max 7 Mental Ray渲染器全攻...
     推荐 电脑艺术设计大师之路#5-探索图...
     推荐 用Photoshop设计微形3D界面01
     推荐 3DS Max 7 Mental Ray渲染器全攻...
     推荐 Firewoks 营造残破纹理02
     
     
     
     
     
    设为首页 | 加入收藏 | 关于学校|  对外事业 | 联系站长 | 友情链接 | 咨询留言