• 第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)


    一. 监视锁(Monitor和lock)

    1. Monitor类,限定线程个数的一把锁,两个核心方法:

      Enter:锁住某个资源。

      Exit:退出某一个资源。

    测试案例:开启5个线程同时对一个变量进行自增操作,结果变量有序的输出,说明该锁同时只允许一个线程访问。

    但是写法很麻烦,每次都要try-catch-finally,还要声明bool变量。这个时候lock语法糖就很好的解决了这个问题。

     代码实践:

     1 static object lockMe = new object();
     2         {
     3                 for (int i = 0; i < 5; i++)
     4                 {
     5                     Task.Factory.StartNew(() =>
     6                     {
     7                         for (int j = 0; j < 100; j++)
     8                         {
     9                             var b = false;
    10                             try
    11                             {
    12                                 Monitor.Enter(lockMe, ref b);
    13                                 Console.WriteLine(num++);
    14                             }
    15                             catch (Exception)
    16                             {
    17 
    18                                 throw;
    19                             }
    20                             finally
    21                             {
    22                                 if (b)
    23                                 {
    24                                     Monitor.Exit(lockMe);
    25                                 }
    26                             }
    27 
    28                         }
    29 
    30                     });
    31                 }
    32             }     

    2. lock语法糖

      使用很简单,声明一个静态的object类型变量,调用lock语法糖,将共享变量放入其中,即可保证lock内同时只能一个线程访问。

     代码实践:

     1             {
     2                 for (int i = 0; i < 5; i++)
     3                 {
     4                     Task.Factory.StartNew(() =>
     5                     {
     6                         for (int j = 0; j < 100; j++)
     7                         {
     8                             lock (lockMe)
     9                             {
    10                                 Console.WriteLine(num++);
    11                             }
    12                         }
    13                     });
    14                 }
    15             }

    二. 混合锁

    1. 简介:混合锁=用户模式锁+内核模式锁,先在用户模式下内旋,如果超过一定的阈值,会切换到内核锁,在内旋模式下,我们会看到大量的Sleep(0),Sleep(1),Yield等语法。

      Thread.Sleep(1) 让线程休眠1ms

      Thread.Sleep(0) 让线程放弃当前的时间片,让本线程更高或者同等线程得到时间片运行。

      Thread.Yield() 让线程立即放弃当前的时间片,可以让更低级别的线程得到运行,当其他thread时间片用完,本thread再度唤醒。

     混合锁包括以下三种:ManualResetEventSlim、SemaphoreSlim、ReaderWriterLockSlim,这三种混合锁,要比他们对应的内核模式锁 (ManualResetEvent、Semaphore、ReaderWriterLock),的性能高的多。

    2. ManualResetEventSlim

      构造函数默认为false,可以使用Wait方法替代WaitOne方法,支持任务取消. (详细的代码同内核版本类似,这里不做测试了)

    3. SemaphoreSlim

      用法和内核版本类似,使用Wait方法代替WaitOne方法,Release方法不变。(详细的代码同内核版本类似,这里不做测试了)

    4. ReaderWriterLockSlim

      用法和内核版本类似,但是四个核心方法换成了:

      锁读的两个核心方法:EnterReadLock、ExitReadLock。

      锁写的两个核心方法:EnterWriteLock、ExitWriteLock。

      (详细的代码同内核版本类似,这里不做测试了)

  • 相关阅读:
    shell-条件测试
    51Nod 1279 扔盘子 (思维+模拟)
    51Nod 1042 数字0-9的数量(数位DP)
    Codeforces 1138B Circus (构造方程+暴力)
    51nod 1133 不重叠的线段 (贪心,序列上的区间问题)
    51nod 1091 线段的重叠(贪心)
    EOJ Monthly 2019.2 E 中位数 (二分+中位数+dag上dp)
    牛客练习赛39 C 流星雨 (概率dp)
    牛客练习赛39 B 选点(dfs序+LIS)
    Educational Codeforces Round 57
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/8315212.html
Copyright © 2020-2023  润新知