首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Monitor.Pulse和Monitor.Wait的优势是什么?

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

Stack Overflow用户
提问于 2011-07-05 04:16:46
回答 4查看 5.1K关注 0票数 7

我对并发编程比较陌生,正在尝试理解使用Monitor.Pulse和Monitor.Wait的好处。

MSDN的示例如下:

代码语言:javascript
复制
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());
    }
}

我看不出用Wait和Pulse代替这个有什么好处:

代码语言:javascript
复制
    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());
            }
        }
    }

任何帮助都是非常感谢的。谢谢

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-07-05 04:28:48

要描述“优势”,一个关键问题是“超越什么?”如果您的意思是“优先于热循环”,那么,CPU利用率是显而易见的。如果你的意思是“优先于睡眠/重试循环”-你可以得到更快的响应(Pulse不需要等待很长时间),并且使用更低的CPU (你不需要不必要地唤醒2000次)。

不过,一般来说,人们的意思是“优先于Mutex等”。

我倾向于广泛地使用它们,甚至优先于互斥、重置事件等;原因:

  • 它们很简单,涵盖了我需要的大多数场景
  • 它们相对便宜,因为它们不需要一直到操作系统句柄(不像互斥等,它是属于操作系统的)
  • 我通常已经使用lock来处理同步,所以,当我需要等待某些东西时,我很可能已经有了一个互斥锁(
  • )它实现了我的正常目标-允许两个线程以托管的方式相互通知完成-
  • 我很少需要互斥锁等的其他功能(比如成为inter-process)
票数 12
EN

Stack Overflow用户

发布于 2011-07-05 04:28:19

您的代码片段中有一个严重的缺陷,当SecondThreadTwo()试图在空队列上调用Dequeue()时,它将严重失败。您可能是通过让FirstThreadTwo()在使用者线程之前执行一小段时间(可能是先启动它)才能让它工作。这是一个意外,在运行这些线程一段时间或使用不同的机器负载启动它们后,它将停止工作。这样可以意外地在相当长的一段时间内无差错地工作,很难诊断出偶尔的故障。

没有办法编写一个锁定算法来阻塞使用者,直到队列变为非空,只使用lock语句。一个不断进入和退出锁的繁忙循环是有效的,但它是一个非常糟糕的替代品。

编写这类代码最好留给线程专家,很难证明它在所有情况下都能工作。不只是没有像这样的失败模式或线程竞争。而且还具有避免死锁、活锁和线程护送的算法的一般适应性。在.NET的世界里,大师是Jeffrey Richter和Joe Duffy。他们把锁设计当做早餐吃,无论是在书中还是在博客和杂志文章中都是如此。窃取他们的代码是预期的,也是被接受的。并通过在System.Collections.Concurrent命名空间中的添加部分地进入.NET框架。

票数 4
EN

Stack Overflow用户

发布于 2011-07-05 04:20:42

正如您所猜测的那样,使用Monitor.Pulse/Wait可以提高性能。获取锁是一个相对昂贵的操作。通过使用Monitor.Wait,您的线程将处于休眠状态,直到其他线程通过“Monitor.Pulse”唤醒您的线程。

您将看到TaskManager中的不同之处,因为即使队列中没有任何内容,也会锁定一个处理器核心。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6575723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档