monitor关键字可以锁定对象,lock为互斥锁,可以锁代码,但二者的实质一样的,lock也是使用monitor的enter和exit实现的,实质上只是将该对象作为一个标识而已,当一个线程尝试进入到被lock或monitor锁住的代码,都需要把当前lock对象和已存在的锁对象进行一一对比,使用object.referenceEquals()。
monitor类所以名义上说的是锁一个对象,但实际上仍然只是锁enter和exit之间的代码,而并不是锁该对象的所有方法,详见如下一实例:
线程tr2的执行函数使用monitor.enter和exit锁住了cell对象,但其中间执行的代码和cell对象并没有关系,而tr1线程直接使用cell对象的方法,在两个线程同时进行的时候,我们发现线程tr2的锁并不影响tr1对该对象方法的调用,输出结果如下,read和write交替输出。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication6
{
class Program
{
static void Main(string[] args)
{
Cell cell = new Cell();
CellRead cr = new CellRead(cell);
CellWrite cw = new CellWrite(cell);
Thread tr1 = new Thread(new ThreadStart(cr.Read));
Thread tr2 = new Thread(new ThreadStart(cw.Write));
tr1.Name = "tr1";
tr2.Name = "tr2";
tr2.Start();
tr1.Start();
Console.Read();
}
}
class Cell
{
public void read2()
{
Console.WriteLine("read2");
}
public void write2()
{
Console.WriteLine("write2");
}
}
class CellRead
{
Cell cell;
public CellRead(Cell cell)
{
this.cell = cell;
}
public void Read()
{
//Monitor.Enter(cell); //线程tr1并没有尝试锁住cell
for (int i = 1; i < 200; i++)
{
cell.read2();
}
//Monitor.Exit(cell);
}
}
class CellWrite
{
Cell cell;
public CellWrite(Cell cell)
{
this.cell = cell;
}
public void Write()
{
Monitor.Enter(cell);
for (int i = 1; i < 200; i++)
{
Console.WriteLine("write");
}
Monitor.Exit(cell);
}
}
}
但如果我们把CellRead类的read方法的锁注释打开,再执行,则结果就只能是其中read线程必须等write线程锁解开后才能执行了,结果如下: