ReaderWriterLock类

通常来讲,一个类型的实例对于并行的读操作是线程安全的,但是并行地更新操作则不是(并 行地读和更新也不是)。 这对于资源也是一样的,比如一个文件。当保护类型的实例安全时,使用一个简单的排它锁即解决问题,但是当有很多的读操作 而偶然的更新操作这就很不合理的限制了并发。一个例子就是这在一个业务程序服务器中,为了快速查找把数据缓存到静态字段中。 在这个方案中,ReaderWriterLock类被设计成提供最大容量的锁定。

ReaderWriterLock为读和写的锁提供了 不同的方法——AcquireReaderLock和AcquireWriterLock。两个方法都需要一个超时参数,并且在超时发生后抛出 ApplicationException异常(不同于大多数线程类的返回false等效的方法)。在资源争用严重的时候发生超时相当容易。

调 用 ReleaseReaderLock或ReleaseWriterLock释放锁。 这些方法支持嵌套锁,ReleaseLock方法也支持一次清除所有嵌套级别的锁。(你可以随后调用RestoreLock类重新锁定相同的级别,它在 ReleaseLock之前执行——如此来模仿Monitor.Wait的锁定切换行为)。

你 可以调用AcquireReaderLock开始一个read-lock ,然后通过UpgradeToWriterLock把它升级为write-lock。这个方法返回一个可能被用于调用 DowngradeFromWriterLock的信息。这个方式允许读程序临时地请求写访问同时不必必须在降级之后重新排队列。

在接 下来的这个例子中,4个线程被启动:一个不停地往列表中增加项目;另一个不停地从列表中移除项目;其它两个不停地报告列表中项目的个数。前两者获得写的 锁,后两者获得读的锁。每个锁的超时参数为10秒。(异常处理一般要使用来捕捉ApplicationException,这个例子中出于方便而省略了)

class Program {
  static ReaderWriterLock rw = new ReaderWriterLock ();
  static List <int> items = new List <int> ();
  static Random rand = new Random ();
 
  static void Main (string[] args) {
    new Thread (delegate() { while (true) AppendItem(); } ).Start();
    new Thread (delegate() { while (true) RemoveItem(); } ).Start();
    new Thread (delegate() { while (true) WriteTotal(); } ).Start();
    new Thread (delegate() { while (true) WriteTotal(); } ).Start();
  }
 
  static int GetRandNum (int max) { lock (rand) return rand.Next (max); }
 
  static void WriteTotal() {
    rw.AcquireReaderLock (10000);
    int tot = 0; foreach (int i in items) tot += i;
    Console.WriteLine (tot);
    rw.ReleaseReaderLock();
  }
 
 static void AppendItem () {
    rw.AcquireWriterLock (10000);
    items.Add (GetRandNum (1000));
    Thread.SpinWait (400);
    rw.ReleaseWriterLock();
  }
 
  static void RemoveItem () {
    rw.AcquireWriterLock (10000);
    if (items.Count > 0)
      items.RemoveAt (GetRandNum (items.Count));
    rw.ReleaseWriterLock();
  }
}

往List中加项目要比移除快一些,这个例子在AppendItem中包含了SpinWait来保持项目总数平衡。

按照请求到达的顺序,一共有四种 
      Reader-Reader,第二个不需等待,直接获得读控制权; 
      Reader-Writer,第二个需要等待第一个调用ReleaseReaderLock()释放读控制权后,才能获得写控制权; 
      Writer-Writer,第二个需要等待第一个调用ReleaseWriterLock()释放写控制权后,才能获得写控制权; 
      Writer-Reader,第二个需要等待第一个调用ReleaseWriterLock()释放写控制权后,才能获得读控制权。

ReaderWriterLock类(转)的更多相关文章

  1. C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步

    摘要:C#提供了System.Threading.ReaderWriterLock类以适应多用户读/单用户写的场景.该类可实现以下功能:如果资源未被写操作锁定,那么任何线程都可对该资源进行读操作锁定, ...

  2. 使用ReaderWriterLock类实现多用户读/单用户写同步

    使用ReaderWriterLock类实现多用户读/单用户写同步[1] 2015-03-12 应用程序在访问资源时是进行读操作,写操作相对较少.为解决这一问题,C#提供了System.Threadin ...

  3. c# ReaderWriterLock类

    先前也知道,Monitor实现的是在读写两种情况的临界区中只可以让一个线程访问,那么如果业务中存在”读取密集型“操作,就 好比数据库一样,读取的操作永远比写入的操作多.针对这种情况,我们使用Monit ...

  4. 【转】【Thread】ReaderWriterLock 读写锁

    ReaderWriterLock类 通常来讲,一个类型的实例对于并行的读操作是线程安全的,但是并行地更新操作则不是(并行地读和更新也不是). 这对于资源也是一样的,比如一个文件.当保护类型的实例安全时 ...

  5. C#必须掌握的系统类

    系统类  Type类,Object类,String类, Arrary类,Console类, Exception类,GC类, MarshalByRefObject类, Math类. DateTime结构 ...

  6. C#多线程---ReaderWriterLock实现线程同步

    一.简介 当我们需要对一个共享资源多次读取的时候,用前面Monitor的同步锁就没有必要了.因为同步锁每次只允许一个线程访问共享资源,其他线程都会阻塞. 此时,通过ReaderWriterLock类可 ...

  7. Java类的继承与多态特性-入门笔记

    相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...

  8. C#线程入门---转载

    C#中的线程(一)入门 文章系参考转载,英文原文网址请参考:http://www.albahari.com/threading/ 作者 Joseph Albahari,  翻译 Swanky Wu 中 ...

  9. C#中的线程(一)入门

    文章系参考转载,英文原文网址请参考:http://www.albahari.com/threading/ 作者 Joseph Albahari,  翻译 Swanky Wu 中文翻译作者把原文放在了& ...

随机推荐

  1. VS2010 EntityFramework Database First

    本文演练介绍如何使用实体框架进行 Database First 开发.通过 Database First,可以从现有数据库对模型进行反向工程处理.模型存储在一个 EDMX 文件(扩展名为 .edmx) ...

  2. c#通过反射获取类上的自定义特性

    c#通过反射获取类上的自定义特性 本文转载:http://www.cnblogs.com/jeffwongishandsome/archive/2009/11/18/1602825.html 下面这个 ...

  3. c#WebBrowser进阶

    WebBrowser的基本功能就是访问网页,但是由于它本身就不在主线程上面,所以程序判断它什么时候加载完成了,比较麻烦.为此我集合从网上找到的内容,做了一个例子. 其中包括了给WebBrowser设置 ...

  4. js 框架都有哪几种(转载)

    目前来看,js框架以及一些开发包和库类有如下几个,Dojo .Scriptaculous .Prototype .yui-ext .Jquery .Mochikit.mootools .moo.fxD ...

  5. 把DataSet转换成JSON

    /// <summary> /// dataTable转换成Json格式 /// </summary> /// <param name="dt"> ...

  6. [Python][flask][flask-wtf]关于flask-wtf中API使用实例教程

    简介:简单的集成flask,WTForms,包括跨站请求伪造(CSRF),文件上传和验证码. 一.安装(Install) 此文仍然是Windows操作系统下的教程,但是和linux操作系统下的运行环境 ...

  7. C++ 实现设计模式之观察者模式

    1. 什么是观察者模式? 观察者模式(有时又被称为发布-订阅Subscribe>模式.模型-视图View>模式.源-收听者Listener>模式或从属者模式)是软件设计模式的一种.在 ...

  8. NGUI系列教程一

    NGUI是Unity的一个插件,使用它来制作你的游戏UI必定将事半功倍.为什么这么说呢?首先我们说说GUI与NGUI的区别,GUI是Unity自带的绘制界面工具,它的成像原理是基于表层的,所以执行效率 ...

  9. Unity3d Shader开发(三)Pass(Fog )

    雾参数用于雾命令控制. 雾化是通过混合已生成的像素的颜色和基于到镜头的距离来确定的一个不变色来完成.雾化不会改变已经混合的像素的透明度值,只是改变RGB值. Syntax 语法 Fog { Fog C ...

  10. Cygwin下设置ls显示颜色

    vi ~/.bashrc 找到alias ls="xxxxxxxxxxxxxxxxxxxxxxxx"这一项,把注释去掉 修改后的这一行为: alias ls='ls -hF --c ...