C# - 使用Monitor

时间:2015-01-24 13:30:00

标签: c# multithreading

我想了解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();                        
    }
}

1 个答案:

答案 0 :(得分:2)

lock语句在幕后使用Monitor.EnterMonitor.Exit

所以你的代码

static void m1()
{
    lock(obj)
    {
        Monitor.Enter(obj);
        Console.WriteLine("m1");
    }
}

实际上获取两次,但只有发布一次。如果m1m2之前获得锁定,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: