欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

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

发布时间:2023/12/10 55 豆豆

一. 监视锁(Monitor和lock)

1. Monitor类,限定线程个数的一把锁(Synchronized lock是他的语法糖),两个核心方法:

  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。

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

 

总结

以上是生活随笔为你收集整理的第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。