【问题标题】:Thread synchronization with Monitor.Pulse NOT working as expected与 Monitor.Pulse 的线程同步未按预期工作
【发布时间】:2016-09-06 08:03:40
【问题描述】:

我有两个方法,first() 和 second(),我将它们分配给两个线程。

以下是我的第二种和第一种方法

     public void first()
    {
        lock (this)
        {
            Monitor.Wait(this);   

            Console.WriteLine("First");
            Monitor.Pulse(this);
        }
    }

    public void second()
    {
        lock (this)
        {
            //Monitor.Wait(this);
            Console.WriteLine("Second");
            Monitor.Pulse(this);
        }
    }

问题出在控制台上,只有“Second”被打印出来。 即使我在 second() 中有 Monitor.Pulse() 来通知控件应该切换到 first() 但这并没有发生。

我关注msdn关注https://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx

如果s 线程没有在 second() 中使用Monitor.Pulse() 将控制权转移到f 线程,我们将不胜感激

以下是我的 Main()

        test t = new test();
        test1 t1 = new test1();
        Thread f = new Thread(new ThreadStart(t.first));
        Thread s = new Thread(new ThreadStart(t1.second));
        f.Start();
        s.Start();
        f.Join();
        s.Join();

【问题讨论】:

    标签: c# .net multithreading thread-synchronization


    【解决方案1】:

    生产者/消费者示例适用于单元的一个实例。我认为你也应该这样做。您的“第一”和“第二”对“this”的引用是不同的。

    【讨论】:

    • 即使解决了这个问题,这里仍然存在竞争,second 假定first 获得了锁,并在second 获得锁之前输入了Wait。 (因为 Pulse 没有任何人 Waiting 被丢弃)
    • @Damien_The_Unbeliever 但这个答案工作正常。
    • @Alex - 它会 - 一些的时间。这是一场竞赛,看哪个线程实际上首先执行lock(this) 行,并且不是保证
    • @Damien_The_Unbeliever 如何解决?
    • @Alex - 这取决于您的实际问题/要求。大多数修复虽然是“抛弃Pulse/Wait并使用更合适的机制” - 无论是不同的同步原语还是例如一个线程安全的集合。
    【解决方案2】:

    由于您初始化了 Test-class 的两个实例(或者您有两个单独的类,TestTest1),因此您在这两个方法中使用的 this-keyword 指的是两个单独的对象.

    创建一个两个方法都可以访问的静态对象,而不是锁定上下文对象,然后锁定它:

    public class Test
    {
        static object _key = new object();
    
        public void First()
        {
            lock (_key)
            {
                Monitor.Wait(_key);
                Console.WriteLine("First");
                Monitor.Pulse(_key);
            }
        }
    
        public void Second()
        {
            lock (_key)
            {
                Console.WriteLine("Second");
                Monitor.Pulse(_key);
            }
        }
    }
    

    First()Second() 放在同一个类中,并创建该类的两个实例而不是一个Test 和一个Test1,您应该会看到预期的结果,即程序将是

    Second
    First
    

    编辑:作为Damien points out though,这也不能保证有效,因为它假定First() 是第一个获得锁的。

    【讨论】:

    • 只有当First事实上第一个成功获取lock 的方法时,您才会看到该输出,这在您分拆时绝不保证两个线程来执行这些方法。
    猜你喜欢
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    相关资源
    最近更新 更多