博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Monitor 是MSDN错了还是我错了?

Posted on 2010-10-03 16:13  qianyz  阅读(634)  评论(2编辑  收藏  举报

MSDN上介绍Monitor时很模糊的,在Enter(obj) 的时候如果能够锁定就进入临界区,否则有其他线程已经锁定的话

只能等待,那只有放入等待队列了,拥有锁的线程在使用完后Exit(obj),他不会通知处于等待队列中的线程进入就绪队

列,但是看下面 的代码:


class MonitorSample
{
    public static object obj = new object();

    public static void P1()
    { 
      Monitor.Enter(obj)

      {
      
          for (int i = 0; i < 2; ++i)
          {
              i++;
              i--;
          }

Monitor.Exit(obj);
      }
      Console.WriteLine("1");
    }

    public static void P2()
    {
        Monitor.Enter(obj)

        {
        
            for (int i = 0; i < 2; ++i)
            {
                i++;
                i--;
            }
         Monitor.Exit(obj);

        }
        Console.WriteLine("2");
    }

    public static void P3()
    {
         Monitor.Enter(obj)  

      {
         
            for (int i = 0; i < 2; ++i)
            {
                i++;
                i--;
            }
      Monitor.Exit(obj);

        }
        Console.WriteLine("3");
    }
    static void Main(string[] args)
    {
        Thread th1 = new Thread(new ThreadStart(P1));
        Thread th2 = new Thread(new ThreadStart(P2));
        Thread th3 = new Thread(new ThreadStart(P3));
        th1.Start();
      
        th2.Start();
        th3.Start();

        Console.Read();

    }
}

按照MSDN上的说法,在一个线程拥有obj锁的时候,这时其他线程要想访问该对象只有等待放入等待队列,那么看上面的例子,

三个线程中肯定有一个会先进入,余下两个只能等待放入等待队列,比如P1先进入,则P2,P3就放入等待队列,P1执行完后调用了

Exit(obj),但是Exit(obj)并不会通知等待队列的P2,P3到就绪队列去获取锁,也没有调用pause去通知,那么上面的P2,P3肯定要死锁,但是

结果却不是死锁,不知原因是什么?希望高手解疑s

2011.5.09 

最近在使用的时候发现,调用enter(obj)会进入就绪对列,等待获取锁,Exit(obj)之后,就绪队列中的第一个线程会获取该锁,但是Exit(obj)不会通知在等待队列中的

线程进入就绪对列。

class MonitorSample
    {
        public static object obj = new object();

        public static void P1()
    {
      
        Console.WriteLine(" b enter 1");
        Monitor.Enter(obj);
        Console.WriteLine("enter 1");
          Console.WriteLine("P1  "+Thread.CurrentThread.GetHashCode());
          Monitor.Wait(obj);
             Console.WriteLine("P1  "+Thread.CurrentThread.GetHashCode());
             Monitor.PulseAll(obj);
             Monitor.Exit(obj);
    
    }

        public static void P2()
    {
        Console.WriteLine(" b enter 2");
          Monitor.Enter(obj);
          Console.WriteLine("enter 2");
          Console.WriteLine("P2  "+Thread.CurrentThread.GetHashCode());
          Monitor.Wait(obj);
             Console.WriteLine("P2  "+Thread.CurrentThread.GetHashCode());
             Monitor.PulseAll(obj);
             Monitor.Exit(obj);
    }

        public static void P3()
    {
        Console.WriteLine(" b enter 3");
        Monitor.Enter(obj);
        Console.WriteLine("enter 3");
        Console.WriteLine("P3  " + Thread.CurrentThread.GetHashCode());
        Monitor.PulseAll(obj);
            Monitor.Wait(obj);
        Console.WriteLine("P3  " + Thread.CurrentThread.GetHashCode());
        Monitor.Exit(obj);
    }
        static void Main(string[] args)
        {
            Thread th1 = new Thread(new ThreadStart(P1));
            Thread th2 = new Thread(new ThreadStart(P2));
            Thread th3 = new Thread(new ThreadStart(P3));
           
            th1.Start();
            th2.Start();
           
            th3.Start();
           
            Console.Read();


        }
    }