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. ubuntu12修改ulimit

    第一步:配置/etc/security/limits.confsudo vim /etc/security/limits.conf文件尾追加 * hard nofile 40960* soft nof ...

  2. javascript控制子页面对父页面控件操作

    //赋值 window.parent.document.getElementById("partyid_trade_edit").value = data.data.partyid ...

  3. LPC17XX 数据手册摘要之系统时钟与功率控制

    系统时钟与功率控制 一.系统时钟 LPC17XX有三个独立的时钟振荡器,分别是主振荡器(MIAN_OSC).内部RC振荡器(IRC_OSC).实时时钟振荡器(RTC_OSC).LPC17XX时钟框图如 ...

  4. css中>,+,~的用法

    1.>的用法 A>B选择A的所有子元素B(只选择一代) 2.+的用法 A+B选择紧随着A的兄弟元素B 3.~的用法 A~B选择位置处于A后面的所有兄弟元素B(不包含兄弟元素的子元素)

  5. How to fix “Duplicate sources.list entry …” issue

    The correct format of repository source line is <type of repository>  <location>  <di ...

  6. (转载)c++builder/delphi中透明panel及透明窗口的实现方法_delphi教程

    c++builder/delphi中透明panel及透明窗口的实现方法_delphi教程 可能大多数程序员会问:透明窗口,特别是透明Panel有什么应用价值呢?可别小看它们哦,下面我就来讲讲他们的巨大 ...

  7. Oracle删除所有表

    Oracle 清理用户所有的表 PLSQL中执行语句 select 'drop '||object_type||' '||object_name||';' from user_objects; 结果集 ...

  8. SpringMVC的controller方法中注解方式传List参数使用@RequestBody

    在SpringMVC控制器方法中使用注解方式传List类型的参数时,要使用@RequestBody注解而不是@RequestParam注解: //创建文件夹 @RequestMapping(value ...

  9. 下拉框点链接js

    $("#input_text").click(function(){ $("#input_fonts").show(); }); $("#input_ ...

  10. Firefly是什么?有什么特点?

    原地址:http://bbs.gameres.com/forum.php?mod=viewthread&tid=219285 Firefly是免费.开源.稳定.快速扩展.能 “热更新”的分布式 ...