欢迎来到.net学习网

欢迎联系站长一起更新本网站!QQ:879621940

您当前所在位置:首页 »  .NET本质论第一卷:公共语言运行库教程 » 正文

本教程章节列表

CLR锁的使用与监视器

创建时间:2013年01月21日 23:03  阅读次数:(5397)
分享到:
如图6.13所示,完成例程在工作线程上执行而不是在调用方线程上执行。由于工作方线程的数量是有限的,完成例程应该避免任何长时间的处理。如果长时间处理是必需的,完成例程应该把工作尽量分成小块,以便它们自身可以异步地执行。
异步调用

只讨论异步执行而回避并发问题是不可能的。使用异步方法调用必然在你的程序中引入并发性(concurrency)。尽管并发性可以让你的程序充分利用多个CPU,优美地处理阻塞系统的调用,但并发性也会引入潜在的问题,而这些问题很难诊断、调试和修复。毫无疑问,它们是由锁(lock)而引起的。

使用锁来解决并发问题是顺理成章的:关于多线程的大多数内容都是有关锁的问题。然而锁是一把双刃剑,你应该非常小心地使用它们。如果可能的话,尽可能地避免使用它们。尤其是使用锁的系统很容易产生死锁(deadlock)的情形,而这时的系统将陷入冻结状态。另一个普遍的问题是,由于锁的争用(contention)将导致较差的可伸缩性。当在应用程序的关键部分上占用锁,并且持有锁的时间过长时,死锁的可能性就很大。

避免使用锁的最好方法,就是确保并发任务不需要共亨任何资源。这意味着异步方法需要小心地避免访问静态字段,这些字段可能也同时被调用方的线程访问。此外,如果对Begininvoke的调用传送了任何对象引用,那么,调用线程应该尽量避免在异步方法仍在执行的时候,去访问那个引用对象,通过避免对这些(还有其他)共享资源的访问,就可以在实现并发性的同时,而又不使用锁了。

如果一个资源不得不被共享,你至少还可以考虑使用另一外种不用锁的技术。如果共享资源只是一个简单地System.Int32或System,Single类型,那么,Sstem.Theading.Interlocked类型提供的一些方法,可用于以线程安全(thread-safe)的方式改写(overwrite)、递增(increment)或递减(decrement)共享值。这些方法使用特定处理程序(processor-specific)的指令自动执行操作。使用这些方法比使用锁要快一些,并且决不会导致死锁,因为没有锁被占用。

在某些不得不用到锁的情下,CLR也提供了对锁的支持.CLR提供了两种基本类型构锁。一种是基于System.Threading.WaitHandle的锁,它反映Win32事件以及互斥地同步共享资源,适用于跨进程的同步,另一种令人更感兴趣的锁是监视器(monitor)和ReadWriterLock。

监视器和ReadWriterLock仅限于在单进程内使用[实际上是在单个AppDomain(应用程序域)]:监视器支持排他锁(exclusive lock),即在同 时间只有一个线程获得对锁的访问。ReadWriteLock支持排他锁和共享锁(shared lock),这使得多个线程可以获取对锁的访问,以提供对受锁保护的资源的只读访问。

监视器可以让你通过系统中的任意对象关联一个锁。然而,由于很少通过锁来使用对象,所以对象存实例化时是没有锁的。当监视器试图在对象上应用一个锁时,CLR将首次消极地分配这个锁。为了让一个对象的锁能被高效地发现,CLR将在对象头(object header)中存储一个索引到同步块(sync lock)中。没有同步块的对象也没有同步块索引。监视器被首次使用在对象上时,将会有一个同步块被分配给对象,而其索引将被存储在对象头中。

我们可以通过System.Threading.Monitoror类型公开基于监视器的锁。该类型有两个静态方法(Enter和Exit),分别用于获取和释放一个对象的锁。这个锁是一个排他锁,并且,在同一时间只有一个线程可以获得它,如果另外一个线程试图在已经被锁定了的对象上获取一个锁,该线程就将被阻塞,直到这个锁变得可用时为止。为了使用这两个监视器方法,c#通过lock语句提供了一个对于异常安全的(exception-safe)构件.例如,考虑下面的方法
Static void Uselt(Bob bob){
Lock (bob)
{
//我自己拥有Bob!!!
Bob.name=”Bob Jones”;
Bob.age=32;
}
}

这个方法等价于下面的方法:
Static void UseIt(Bob bob)
{
Try
{
System.Threading.Monitor.Enter(bob);
//我自己拥有Bob!!!
Bob.name=”Bob Jones”;
Bob.age=32;
}
Finally
{
System.Threading.Monitort.Exit(bob);
}
}

CLR的监视器还提供了Java风格的pulse-and-wait(脉冲并等待)能力,用于执行底层线程同步。推荐您读一读Doug Lea最优秀的著作《Concurrent  Programming in Java》(Addison—Wesley,1999年),这是关于该功能的权威论述。)
来源:.net学习网
说明:所有来源为 .net学习网的文章均为原创,如有转载,请在转载处标注本页地址,谢谢!
【编辑:Wyf】

打赏

取消

感谢您的支持,我会做的更好!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

最新评论

共有评论0条
  • 暂无任何评论,请留下您对本文章的看法,共同参入讨论!
发表评论:
留言人:
内  容:
请输入问题 72+69=? 的结果(结果是:141)
结  果: