zoukankan      html  css  js  c++  java
  • [.net 多线程 ]ReaderWriterLock

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

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

    注意 
    长时间持有读线程锁或写线程锁会使其他线程发生饥饿 (starve)。为了得到最好的性能,需要考虑重新构造应用程序以将写访问的持续时间减少到最小。

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

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

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

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

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

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

      1 static void Main(string[] args)
      2         {
      3             Dictionary<int, string> dic = new Dictionary<int, string>();
      4             ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
      5             Task.Factory.StartNew(() =>
      6             {
      7                 int key = 0;
      8                 while (key <= 1000)
      9                 {
     10                     Thread.Sleep(10);
     11                     string info = $"写线程:{DateTime.Now.ToString("hhMMss-fff")}";
     12                     if (lockSlim.TryEnterWriteLock(20))
     13                     {
     14                         try
     15                         {
     16                             dic.Add(key++, info);
     17                             Console.WriteLine(info);
     18                         }
     19                         catch (Exception ex)
     20                         {
     21                             ;
     22                         }
     23                         finally
     24                         {
     25                             Console.WriteLine($"释放 {info}");
     26                             lockSlim.ExitWriteLock();
     27                         }
     28                     }
     29                 }
     30             });
     31             Task.Factory.StartNew(() =>
     32             {
     33                 while (true)
     34                 {
     35                     Thread.Sleep(100);
     36                     int key = 0;
     37                     if (lockSlim.TryEnterReadLock(20))
     38                     {
     39                         try
     40                         {
     41                             while (key < dic.Count)
     42                             {
     43                                 Console.WriteLine($"读线程1:{dic[key++]}");
     44                             }
     45                         }
     46                         catch (Exception ex)
     47                         {
     48                             ;
     49                         }
     50                         finally
     51                         {
     52                             lockSlim.ExitReadLock();
     53                         }
     54                     }
     55                 }
     56             });
     57             Task.Factory.StartNew(() =>
     58             {
     59                 while (true)
     60                 {
     61                     Thread.Sleep(100);
     62                     int key = 0;
     63                     if (lockSlim.TryEnterReadLock(20))
     64                     {
     65                         try
     66                         {
     67                             while (key < dic.Count)
     68                             {
     69                                 Console.WriteLine($"读线程2:{dic[key++]}");
     70                             }
     71                         }
     72                         catch (Exception ex)
     73                         {
     74                             ;
     75                         }
     76                         finally
     77                         {
     78                             lockSlim.ExitReadLock();
     79                         }
     80                     }
     81                 }
     82             });
     83             Task.Factory.StartNew(() =>
     84             {
     85                 while (true)
     86                 {
     87                     Thread.Sleep(100);
     88                     int key = 0;
     89                     if (lockSlim.TryEnterReadLock(20))
     90                     {
     91                         try
     92                         {
     93                             while (key < dic.Count)
     94                             {
     95                                 Console.WriteLine($"读线程3:{dic[key++]}");
     96                             }
     97                         }
     98                         catch (Exception ex)
     99                         {
    100                             ;
    101                         }
    102                         finally
    103                         {
    104                             lockSlim.ExitReadLock();
    105                         }
    106                     }
    107                 }
    108             });
    109             Task.Factory.StartNew(() =>
    110             {
    111                 while (true)
    112                 {
    113                     Thread.Sleep(100);
    114                     int key = 0;
    115                     if (lockSlim.TryEnterReadLock(20))
    116                     {
    117                         try
    118                         {
    119                             while (key < dic.Count)
    120                             {
    121                                 Console.WriteLine($"读线程4:{dic[key++]}");
    122                             }
    123                         }
    124                         catch (Exception ex)
    125                         {
    126                             ;
    127                         }
    128                         finally
    129                         {
    130                             lockSlim.ExitReadLock();
    131                         }
    132                     }
    133                 }
    134             });
    135             Console.ReadKey();
    136         }
    View Code

    .NET 同步与异步之锁(ReaderWriterLockSlim)(八)

    c#线程同步系列(二) c#中ReaderWriterLock的使用

    读写锁ReaderWriterLockSlim

  • 相关阅读:
    日记搬迁
    学生会管理系统(JavaWeb与数据库课程小实践)
    疯狂忙碌边缘
    英语复习二:每单元的翻译篇章
    Don't always upset yourself !
    一文教你读懂并使用GTD高效时间管理法
    Day05-黑马学习篇(二)matplot基本绘图函数集合
    Day04-黑马学习篇(一)matplot画图基本要点
    Day03-基础篇(四)Pandas与数据清洗
    Day02 基础篇(三)用NumPy快速处理数据
  • 原文地址:https://www.cnblogs.com/deepminer/p/9053933.html
Copyright © 2011-2022 走看看