前言
1、Monitor
Monitor是一个C#中System.Threading下的静态类,它提供了用于线程同步的方法和信号量。它们用来实现进入和退出临界区,以确保在同一时间只有一个线程可以访问共享资源。它有两个重要方法 Monitor.Enter和Monitor.Exit。
使用示例:
public class MyClass{static readonly object lockObject = new object();public void MonitorThead(){// 在 C#4.0以上版本,Monitor.Enter(_object,ref _lockTaken)// 的重载函数获取独占锁和指定的对象,并自动设置一个值,指示是否已使用锁。Monitor.Enter(lockObject);try{int j = 0;for (int i = 0; i < 10; i++){Thread.Sleep(100);Console.Write($"{j++},");}Console.WriteLine();}finally{//在 C#4.0以上版本 这里判断//if(_lockTaken)//{// Monitor.Exit(lockObject);//}Monitor.Exit(lockObject);}}}internal class Program{static void Main(string[] args){Thread[] Threads = new Thread[2];for (int i = 0; i < 2; i++){Threads[i] = new Thread(new ThreadStart(new MyClass().MonitorThead));Threads[i].Name = "Name " + i;}foreach (Thread t in Threads)t.Start();//Console.WriteLine("Hello, World!");}}
效果:

例子中我们使用Monitor来保护lockObject,使得在同一时刻只有一个线程try中的代码。如果有其他线程尝试进入会被阻塞,直到锁被释放。
2、Lock
Lock想必经常使用多线程的程序员比较熟悉了。它是C#中的一个关键字,功能其实与Monitor类似。其实Lock就是Monitor类的语法糖,编译器会将lock关键字转换为对Monitor.Enter和Monitor.Exit的调用,让语法更加简洁。下面我们将用案例反编译后的中间语言看看它们的关系。
使用示例:
public class MyClass{//private object lockObject = new object(); 使用更安全static readonly object _object = new object();public void LockThead(){lock (_object){int j = 0;for (int i = 0; i < 10; i++){Thread.Sleep(100);Console.Write($"{j++},");}Console.WriteLine();}}}static void Main(string[] args){Thread[] Threads = new Thread[2];for (int i = 0; i < 2; i++){Threads[i] = new Thread(new ThreadStart(new MyClass().LockThead));Threads[i].Name = "Name " + i;}foreach (Thread t in Threads)t.Start();}//欢迎关注公众号:DOTNET开发跳槽,领取海量面试题。//加微信号xbhpnet入群交流
反编译的部分代码:

以上是反编译IL代码的部分切图,从反编译IL的结果可以看出,Lock底层也用了Monitor。Lock效果跟上面的一样。只不过代码更加简洁美观。
注意Object对象的声明方式:
//由于是私有的,每一个实例都有自己对象,所以使用更安全和稳定private object lockObject = new object();//static readonly 由于是静态只读,全局只用一个,相当于全局锁static readonly object _object = new object();
本案例为了展示效果使用了static readonly object。
结语