第十三节:实际开发中使用最多的监视锁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。

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

 

 

 

 

 

posted @ 2018-01-19 08:21  Yaopengfei  阅读(1568)  评论(1编辑  收藏  举报