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

  • 相关阅读:
    LeetCode 453 Minimum Moves to Equal Array Elements
    LeetCode 112 Path Sum
    LeetCode 437 Path Sum III
    LeetCode 263 Ugly Number
    Solutions and Summay for Linked List Naive and Easy Questions
    AWS–Sysops notes
    Linked List
    All About Linked List
    datatable fix error–Invalid JSON response
    [转]反编译c#的相关问题
  • 原文地址:https://www.cnblogs.com/rogge7/p/6393753.html
Copyright © 2011-2022 走看看