线程同步 - ReaderWriterLock

  •  static void Main()
    {
      Random rnd = new Random(DateTime.Now.Millisecond);
      Queue<int> queue = new Queue<int>();
      ReaderWriterLock locker = new ReaderWriterLock();

      // 创建一个写线程
      Thread w = new Thread(delegate()
      {
        while (true)
        {
          try
          {
            locker.AcquireWriterLock(Timeout.Infinite);

            int i = rnd.Next(100, 999);
            queue.Enqueue(i);
            Console.Write("Write:{0} / ", i);
            Thread.Sleep(500);
          }
          finally
          {
            locker.ReleaseWriterLock();
          }
        }
      });

      w.Start();
  • // 创建三个读线程
      for (int i = 0; i < 3; i++)
      {
        Thread r = new Thread(delegate()
        {
          while (true)
          {
            try
            {
              locker.AcquireReaderLock(Timeout.Infinite);

              if (queue.Count > 0)
              {
                int x = queue.Dequeue();
                Console.WriteLine("{0}:{1}", Thread.CurrentThread.Name, x);
              }
            }
            finally
            {
              locker.ReleaseReaderLock();
            }
          }
        });

        r.Name = "Read" + (i + 1).ToString();
        r.Start();
      }

      Console.WriteLine("Press any key to exit...");
      Console.ReadKey(true);
    }
  • 文字摘自 MSDN
    -----------------------

    ReaderWriterLock 定义支持单个写线程和多个读线程的锁。

    ReaderWriterLock 用于同步对资源的访问。在任一特定时刻,它允许多个线程同时进行读访问,或者允许单个线程进行写访问。在资源不经常发生更改的情况下,ReaderWriterLock 所提供的吞吐量比简单的一次只允许一个线程的锁(如 Monitor)更高。

    在多数访问为读访问,而写访问频率较低、持续时间也比较短的情况下,ReaderWriterLock 的性能最好。多个读线程与单个写线程交替进行操作,所以读线程和写线程都不会长时间阻止。

    一个线程可以持有读线程锁或写线程锁,但是不能同时持有两者。若要获取写线程锁,请使用 UpgradeToWriterLock 和 DowngradeFromWriterLock,而不要通过释放读线程锁的方式获取。

    递归锁请求会增加锁上的锁计数。

    读线程和写线程将分别排入各自的队列。当线程释放写线程锁时,此刻读线程队列中的所有等待线程都将被授予读线程锁;当已释放所有读线程锁时,写线程队列中处于等待状态的下一个线程(如果存在)将被授予写线程锁,依此类推。换句话说,ReaderWriterLock 在一组读线程和一个写线程之间交替进行操作。

    当写线程队列中有一个线程在等待活动读线程锁被释放时,请求新的读线程锁的线程会排入读线程队列。即使它们能和现有的阅读器锁持有者共享并发访问,也不会给它们的请求授予权限;这有助于防止编写器被阅读器无限期阻止。

    大多数在 ReaderWriterLock 上获取锁的方法都采用超时值。使用超时可以避免应用程序中出现死锁。例如,某个线程可能获取了一个资源上的写线程锁,然后请求第二个资源上的读线程锁;同时,另一个线程获取了第二个资源上的写线程锁,并请求第一个资源上的读线程锁。如果不使用超时,这两个线程将出现死锁。

    如果超时间隔过期并且没有授予锁请求,则此方法通过引发 ApplicationException 将控制返回给调用线程。线程可以捕捉此异常并确定下一步要进行的操作。

    超时用毫秒表示。如果使用 System.TimeSpan 指定超时,则所用的值是 TimeSpan 所表示的毫秒整数的总和。下表显示用毫秒表示的有效超时值。

    值 说明
    -----------------
    -1 Infinite.
    0 无超时。
    >0 要等待的毫秒数。

    除了 -1 以外,不允许使用负的超时值。如果要使用 -1 以外的负整数来指定超时,系统将使用零(无超时)。如果指定的 TimeSpan 表示的是 -1 以外的负毫秒数,将引发 ArgumentOutOfRangeException。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值