Monitor:提供同步访问对象的机制。
其实lock关键字就是对Monitor的简化调用,lock最终就编译成Monitor,因此一般不不直接用Monitor类
与lock 语句相比较 Monitor 类是主要优点是:可以添加一个等待被锁定的超时值。这样就不会无限期的等待被锁定。
但是 Monitor 必须手动释放锁。一般把代码写在 try/finally中。
例:
static int number = 5000;
private static object locker1 = new object();
static void ChangeNumber(string str)
{
Monitor.Enter(locker1);//等待没有人锁定locker对象,我就锁定它,然后继续执行
try
{
int num = number - 1;
number = num;
Thread.Sleep(1);
Console.WriteLine(str + " 改变数据 :" + number);
}
finally
{
Monitor.Exit(locker1);//释放locker1对象的锁
}
}
static void Main(string[] args)
{
Thread t1 = new Thread(() =>
{
for (int i = 0; i < 1000; i++)
{
ChangeNumber("t1");
}
});
Thread t2 = new Thread(() => {
for (int i = 0; i < 1000; i++)
{
ChangeNumber("t2");
}
});
//t1.IsBackground = true;
//t2.IsBackground = true;
t1.Start();
t2.Start();
Thread.Sleep(5000);//等待线程执行完毕
Console.WriteLine("改变后:"+number);
Console.ReadKey();
}
Monitor 超时设定方法:
static int number = 5000;
private static object locker1 = new object();
private static object locker2 = new object();
static void ChangeNumber(string str)
{
//传入超时时间,指定等待被锁定的最长时间,如果对象被锁定,TryEnter()会把布尔的引用参数设置为 true 并同步地访问由对象 locker1 锁定的状态。如果另一个线程锁定 locker1 的时间超过 5 毫秒,TryEnter()方法就会把变量 flag 设置为 false,线程不再等待,而是执行其他操作,也许在以后,该线程会尝试再次获得锁定
bool flag = false;
Monitor.TryEnter(locker1,5,ref flag);
if(flag)
{
try
{
int num = number - 1;
number = num;
Thread.Sleep(1);
Console.WriteLine(str + " 改变数据 :" + number);
}
finally
{
Monitor.Exit(locker1);//释放locker1对象的锁
}
}
else
{
Console.WriteLine("已超时!");
}
}
static void Main(string[] args)
{
Thread t1 = new Thread(() =>
{
for (int i = 0; i < 1000; i++)
{
ChangeNumber("t1");
}
});
Thread t2 = new Thread(() => {
for (int i = 0; i < 1000; i++)
{
ChangeNumber("t2");
}
});
//t1.IsBackground = true;
//t2.IsBackground = true;
t1.Start();
t2.Start();
Thread.Sleep(5000);//等待线程执行完毕
Console.WriteLine("改变后:"+number);
Console.ReadKey();
}