什么是Monitor.Pulse和Monitor.Wait的优势?

ser*_*1ty 6 c# concurrency multithreading

我对并发编程有点新意,并试图了解使用Monitor.Pulse和Monitor.Wait的好处.

MSDN的示例如下:

class MonitorSample
{
    const int MAX_LOOP_TIME = 1000;
    Queue   m_smplQueue;

    public MonitorSample()
    {
        m_smplQueue = new Queue(); 
    }
    public void FirstThread()
    {
        int counter = 0;
        lock(m_smplQueue)
        {
            while(counter < MAX_LOOP_TIME)
            {
                //Wait, if the queue is busy.
                Monitor.Wait(m_smplQueue);
                //Push one element.
                m_smplQueue.Enqueue(counter);
                //Release the waiting thread.
                Monitor.Pulse(m_smplQueue); 

                counter++;
            }
        }
    }
    public void SecondThread()
    {
        lock(m_smplQueue)
        {
            //Release the waiting thread.
            Monitor.Pulse(m_smplQueue);
            //Wait in the loop, while the queue is busy.
            //Exit on the time-out when the first thread stops. 
            while(Monitor.Wait(m_smplQueue,1000))
            {
                //Pop the first element.
                int counter = (int)m_smplQueue.Dequeue();
                //Print the first element.
                Console.WriteLine(counter.ToString());
                //Release the waiting thread.
                Monitor.Pulse(m_smplQueue);
            }
        }
    }
    //Return the number of queue elements.
    public int GetQueueCount()
    {
        return m_smplQueue.Count;
    }

    static void Main(string[] args)
    {
        //Create the MonitorSample object.
        MonitorSample test = new MonitorSample();           
        //Create the first thread.
        Thread tFirst = new Thread(new ThreadStart(test.FirstThread));
        //Create the second thread.
        Thread tSecond = new Thread(new ThreadStart(test.SecondThread));
        //Start threads.
        tFirst.Start();
        tSecond.Start();
        //wait to the end of the two threads
        tFirst.Join();
        tSecond.Join();         
        //Print the number of queue elements.
        Console.WriteLine("Queue Count = " + test.GetQueueCount().ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

我无法看到使用Wait And Pulse而不是这样做的好处:

    public void FirstThreadTwo()
    {
        int counter = 0;
        while (counter < MAX_LOOP_TIME)
        {
            lock (m_smplQueue)
            {
                m_smplQueue.Enqueue(counter);
                counter++;
            }
        }
    }
    public void SecondThreadTwo()
    {
        while (true)
        {
            lock (m_smplQueue)
            {
                    int counter = (int)m_smplQueue.Dequeue();
                    Console.WriteLine(counter.ToString());
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

任何帮助都非常感谢.谢谢

Mar*_*ell 12

为了描述"优势",一个关键问题是"什么?".如果你的意思是"优先考虑热循环",那么CPU利用率是显而易见的.如果你的意思是"优先于睡眠/重试循环" - 你可以获得更快的响应(Pulse不需要等待那么长)使用较低的CPU(你没有不必要地唤醒2000次).

但一般来说,人们的意思是"优先考虑Mutex等".

我倾向于广泛使用这些,甚至优先考虑互斥,重置事件等; 原因:

  • 它们很简单,涵盖了我需要的大部分场景
  • 它们相对便宜,因为它们不需要一直到操作系统句柄(不像操作系统拥有的Mutex等)
  • 我通常已经习惯于lock处理同步,所以lock当我需要等待某些东西时,我已经有了很好的机会
  • 它实现了我的正常目标 - 允许2个线程以管理的方式向彼此发出完成信号
  • 我很少需要Mutex等的其他功能(例如进程间)