码迷,mamicode.com
首页 > Windows程序 > 详细

C# ReaderWriterLockSlim

时间:2021-01-05 11:43:39      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:示例   may   public   单线程   run   获取   test   string   success   

ReaderWriterLockSlim-多线程读单线程写

 

注意事项

(1)线程A如果通过EnterReadLock获取到读锁(ReadLock)后,不能在持有读锁的情况下再申请获取写锁(WriteLock)

如果违反了这个规定就报如下错:
Write lock may not be acquired with read lock held. This pattern is prone to deadlocks. Please ensure that read locks are released before taking a write lock. If an upgrade is necessary, use an upgrade lock in place of the read lock.

(2)线程A如果通过EnterReadLock获取到读锁(ReadLock)后,不能在持有读锁的情况下再申请获取可升级读锁(UpgradeableReadLock)

如果违反了这个规定就报如下错:
Upgradeable lock may not be acquired with read lock held

(3)线程A如果通过EnterUpgradeableReadLock获取到可升级读锁(UpgradeableReadLockk)后,可以再持有可升级读锁的情况通过EnterWriteLock获取写锁

 

递归锁

递归锁:同一个线程获取到该锁后可以再获取该锁多次,不会产生死锁。

使用默认构造函数构造的ReaderWriterLockSlim是不允许锁递归的,如果一个线程已经获取到该锁后又获取该锁就会出错,如报错“Recursive upgradeable lock acquisitions not allowed in this mode”

示例如下:

技术图片

 

解决方法:使用允许递归锁的构造方法(即new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion))构造ReaderWriterLockSlim实例

如何判断代码逻辑里会触发递归锁呢,抓住两个要点“同一线程(即ManageThreadId一样)”和“同一个锁”,在线程池里运行的时候,由于可以重用工作线程,很容易触发递归锁的问题,比如这样:线程池线程1获取到UpgradeableReadLock锁后由于后面代码里有长时等待任务,调度器可能调度线程1运行队列里的另一个同样代码的任务,这时由于代码一样线程1再次申请获取UpgradeableReadLock锁(因为上一次他已经获取到该UpgradeableReadLock锁了),就会报错了

 

示例代码:

        static void Main()
        {
            ReaderWriterLockSlimTest();

            Console.Read();
        }

        public static void ReaderWriterLockSlimTest()
        {
            Console.WriteLine($"主线程Id : {Thread.CurrentThread.ManagedThreadId}");

            // 定义共享资源
            var list = new List<string>();

            //  定义ReaderWriterLockSlim共享实例
            //ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); // 允许递归锁
            ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim();

            //TaskMethod0102("task1", 1, list, readerWriterLockSlim);

            var task1 = Task.Run(() => TaskMethod0102("task1", 1, list, readerWriterLockSlim));
            var task2 = Task.Run(() => TaskMethod0102("task2", 2, list, readerWriterLockSlim));
            var task3 = Task.Run(() => TaskMethod0102("task3", 3, list, readerWriterLockSlim));

            //var thread1 = new Thread(() => TaskMethod0102("task1", 1, list, readerWriterLockSlim));
            //var thread2 = new Thread(() => TaskMethod0102("task2", 1, list, readerWriterLockSlim));
            //var thread3 = new Thread(() => TaskMethod0102("task3", 1, list, readerWriterLockSlim));

        }

        public static string TaskMethod0102(string taskName,double seconds,List<string>  list,ReaderWriterLockSlim readerWriterLockSlim)
        {
            try
            {
                Console.WriteLine($"{taskName} want to Read  ,线程Id:{Thread.CurrentThread.ManagedThreadId}");
                //readerWriterLockSlim.EnterReadLock(); // 尝试获取读锁
                readerWriterLockSlim.EnterUpgradeableReadLock(); // 尝试获取可升级读锁
                Console.WriteLine($"{taskName} success to Read ,集合总数:{(list == null ? 0 : list.Count)} ,线程Id:{Thread.CurrentThread.ManagedThreadId}");

                Console.WriteLine($"{taskName} want to Write ,线程Id:{Thread.CurrentThread.ManagedThreadId}");
                readerWriterLockSlim.EnterWriteLock();
                Console.WriteLine($"{taskName} success to Write ,线程Id:{Thread.CurrentThread.ManagedThreadId}");
                list.Add(taskName);

                return "OK";
            }
            catch(Exception ex)
            {
                return "发生异常,异常信息:" + ex.Message;
            }
            finally
            {
                Console.WriteLine($"{taskName } 释放所有的锁 ,线程Id:{Thread.CurrentThread.ManagedThreadId}");
                readerWriterLockSlim.ExitUpgradeableReadLock();
                readerWriterLockSlim.ExitWriteLock();
            }
        }

运行结果:

技术图片

 

C# ReaderWriterLockSlim

标签:示例   may   public   单线程   run   获取   test   string   success   

原文地址:https://www.cnblogs.com/tomorrow0/p/14223556.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!