我想了解Monior.Wait和Monitor.Pulse是如何工作的。 作为练习,我写了以下程序。 我期待在m1之前打印m2。
基本原理:如果m1首先获得锁定,它将等待obj并释放锁定。因此m1不应该在m2之前打印。如果m2获得锁定,则无论如何都会首先打印m2。
但我观察到的是完全不同的: 当我正常运行程序时,只有m1被打印,并且在此之后它保持沉默而没有终止......也许程序在某个地方被卡住了。为了分析它,当我在调试模式下运行程序时,我得到了预期的行为。
有人可以解释一下这里发生了什么吗?此外,对此进行编码以获得预期行为的正确方法是什么?
class Program
{
static object obj = new object();
static void m1()
{
lock(obj)
{
Monitor.Enter(obj);
Console.WriteLine("m1");
}
}
static void m2()
{
lock (obj)
{
Console.WriteLine("m2");
Monitor.Pulse(obj);
}
}
static void Main(string[] args)
{
Thread t1 = new Thread(m1);
Thread t2 = new Thread(m2);
t1.Start();
t2.Start();
}
}
答案 0 :(得分:2)
lock
语句在幕后使用Monitor.Enter
和Monitor.Exit
。
所以你的代码
static void m1()
{
lock(obj)
{
Monitor.Enter(obj);
Console.WriteLine("m1");
}
}
实际上获取锁两次,但只有发布一次。如果m1
在m2
之前获得锁定,obj
上的锁定永远不会被释放,而m2
将永远等待。
(快捷方式:在rextester上运行代码)
更改m1
如下:
static void m1()
{
lock(obj)
{
Monitor.Enter(obj);
Console.WriteLine("m1");
}
Console.WriteLine("m1 has lock on obj: ", Monitor.IsEntered(obj));
}
这将被打印(好吧,..仅在m1首先获得锁定的情况下!):
M1
m1锁定了obj: