代码之家  ›  专栏  ›  技术社区  ›  endian

请有人给我一个简单的例子,说明如何使用C中的System.Monitor?

  •  4
  • endian  · 技术社区  · 16 年前

    我发现系统。监视器非常混乱,尽管我理解线程、锁、死锁、比赛条件、就餐哲学家和所有的爵士乐。通常我使用manualReseteEvent()来进行线程间协调,但我知道这是一个重量级的内核对象,System.Monitor(Enter/Pulse等)效率更高。我一直在谷歌搜索,但找不到一个合理的例子。

    如果SO的工作人员能向我解释这一潜在的美妙构造,我将不胜感激。

    2 回复  |  直到 16 年前
        1
  •  8
  •   Marc Gravell    16 年前

    下面是一个非常简单的例子;调用 Wait 释放锁(允许 Worker 并添加 Main 线程到锁定对象的挂起队列。 工人 然后获取锁,并调用 Pulse :这将移动 主要的 线程进入锁定对象的就绪队列。什么时候? 工人 发行版 锁, 主要的 可以继续工作。

    注意 lock(obj) {...} 只是编译器的糖果 Monitor.Enter / Monitor.Exit 在try/finally块中。

    [编辑:我将示例更改为移动 lock(sync) 早些时候,为了避免(不太可能)错过脉冲的风险]

        static void Main()
        {
            object sync = new object();
            lock (sync)
            {
                ThreadPool.QueueUserWorkItem(Worker, sync);
                Console.WriteLine("Main sleeping");
    
                // wait for the worker to tell us it is ready
                Monitor.Wait(sync);
                Console.WriteLine("Main woke up!");
            }
            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }
        static void Worker(object sync)
        {
            Console.WriteLine("Worker started; about to sleep");
            Thread.Sleep(5000);
            Console.WriteLine("Worker about pulse");
            lock (sync)
            { // notify Main that we did something interesting
                Monitor.Pulse(sync);
                Console.WriteLine("Worker pulsed; about to release lock");
            }
            Console.WriteLine("Worker all done");
        }
    
        2
  •  3
  •   Jon Skeet    16 年前

    看看是否 this part of my threading article 帮助…(那页的后半部分)。它实现了一个生产者/消费者队列:当生产者在队列中生成某个东西(并且发现它是空的——作为一种优化),它向监视器发送脉冲,以唤醒任何等待的线程。当消费者试图从队列中消费但发现它是空的时,它会等待一个脉冲,然后再试一次。

    或者, Joe Albahari's threading tutorial 还有一个关于等待/脉冲的部分。

    它和WaitHandle习惯很相似——尽管坦率地说,我发现我的头脑比WaitHandles更容易,但主要是因为它和我“长大”的Java等待/通知非常类似: