zoukankan      html  css  js  c++  java
  • C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步

    C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步 - mile - 博客园
    http://www.cnblogs.com/lhws/archive/2014/03/31/3636757.html


    • 摘要:C#提供了System.Threading.ReaderWriterLock类以适应多用户读/单用户写的场景。该类可实现以下功能:如果资源未被写操作锁定,那么任何线程都可对该资源进行读操作锁定,并且对读操作锁数量没有限制,即多个线程可同时对该资源进行读操作锁定,以读取数据。

      使用Monitor或Mutex进行同步控制的问题:由于独占访问模型不允许任何形式的并发访问,这样的效率总是不太高。许多时候,应用程序在访问资源时是进行读操作,写操作相对较少。为解决这一问题,C#提供了System.Threading.ReaderWriterLock类以适应多用户读/单用户写的场景。该类可实现以下功能:如果资源未被写操作锁定,那么任何线程都可对该资源进行读操作锁定,并且对读操作锁数量没有限制,即多个线程可同时对该资源进行读操作锁定,以读取数据。如果资源未被添加任何读或写操作锁,那么一个且仅有一个线程可对该资源添加写操作锁定,以写入数据。简单的讲就是:读操作锁是共享锁,允许多个线程同时读取数据;写操作锁是独占锁,同一时刻,仅允许一个线程进行写操作。

      示例代码如下:

    using System;
    using System.Threading;
    
    namespace ProcessTest
    {
        class Program
        {
            //资源
            static int theResource = 0;
            //读、写操作锁
            static ReaderWriterLock rwl = new ReaderWriterLock();
    
            static void Main(string[] args)
            {
                //分别创建2个读操作线程,2个写操作线程,并启动
                Thread tr0 = new Thread(new ThreadStart(Read));
                Thread tr1 = new Thread(new ThreadStart(Read));
                Thread tr2 = new Thread(new ThreadStart(Write));
                Thread tr3 = new Thread(new ThreadStart(Write));
    
                tr0.Start();
                tr1.Start();
                tr2.Start();
                tr3.Start();
    
                //等待线程执行完毕
                tr0.Join();
                tr1.Join();
                tr2.Join();
                tr3.Join();
    
                System.Console.ReadKey();
            }
    
            //读数据
            static void Read()
            {
                for (int i = 0; i < 3; i++)
                {
                    try
                    {
                        //申请读操作锁,如果在1000ms内未获取读操作锁,则放弃
                        rwl.AcquireReaderLock(1000);
                        Console.WriteLine("开始读取数据,theResource = {0}", theResource);
                        Thread.Sleep(10);
                        Console.WriteLine("读取数据结束,theResource = {0}", theResource);
                        //释放读操作锁
                        rwl.ReleaseReaderLock();
                    }
                    catch (ApplicationException)
                    {
                        //获取读操作锁失败的处理
                    }
                }
            }
    
            //写数据
            static void Write()
            {
                for (int i = 0; i < 3; i++)
                {
                    try
                    {
                        //申请写操作锁,如果在1000ms内未获取写操作锁,则放弃
                        rwl.AcquireWriterLock(1000);
                        Console.WriteLine("开始写数据,theResource = {0}", theResource);
                        //将theResource加1
                        theResource++;
                        Thread.Sleep(100);
                        Console.WriteLine("写数据结束,theResource = {0}", theResource);
                        //释放写操作锁
                        rwl.ReleaseWriterLock();
                    }
                    catch (ApplicationException)
                    {
                        //获取写操作锁失败
                    }
                }
            }
        }
    }

    上例中分别创建2个读取线程和2个写入线程,交替进行读、写操作。运行结果如下图:

                       

    观察运行结果,我们很容易看出:读操作锁是共享锁,允许多个线程同时读取数据;写操作锁是独占锁,仅允许一个线程进行写操作。

      如果一个线程在获取读操作锁后,进行读操作的途中,希望提升锁级别,将其变为写操作锁,可以调用ReaderWriterLock类的UpgradeToWriterLock(int timeOut)方法,该方法返回一个LockCookie值,该值保存了UpgradeToWriterLock方法调用前线程锁的状态。待写操作完成后,可调用DowngradeFromWriterLock(LockCookie lockcookie)方法,该方法根据传入的LockCookie参数值,将线程锁恢复到UpgradeToWriterLock方法调用前的状态。具体使用方法,大家可以查看MSDN以获取相关示例。

     =================

    拓:ReaderWriterLockSlim 这个更好

    如何使用C#读写锁ReaderWriterLockSlim_C#教程_脚本之家
    http://www.jb51.net/article/69869.htm

    ReaderWriterLock 类 (System.Threading)
    https://msdn.microsoft.com/zh-cn/library/system.threading.readerwriterlock.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1

  • 相关阅读:
    Android开发-API指南-Manifest介绍
    MSP430G2333下位机乘法运算需要注意的一个问题
    VC++ 6.0使用定时器SetTimer;
    QT编写上位机程序一定要初始化变量以及谨慎操作指针
    QT点击"X"按钮,调用closeEvent()函数来实现调用特定事件(附:粗略介绍QT的信号与槽的使用方法)
    部分LINUX系统由图形界面启动变更为命令行界面启动的方法
    示波器trigger的使用方法
    QT共享库的创建与调用(初级)(附:UI界面不能被改变的其中一个原因)
    随笔:开篇——加入博客园的第N天,变量N无法用char来装载
    c语言课程设计之贪吃蛇代码及思路 c语言课程设计报告之贪吃蛇
  • 原文地址:https://www.cnblogs.com/rogge7/p/6393753.html
Copyright © 2011-2022 走看看