需要帮助来了解AutoResetEvent行为

时间:2018-09-27 14:56:45

标签: c# .net multithreading .net-core

我正在试验.NET的信号结构,并试图在两个线程之间进行简单的协调,但是出了点问题,结果到处都是,有时程序被锁定了。我猜想正在发生某种竞赛情况,但是想让某人解释发生了什么。

    private static readonly AutoResetEvent manual = new AutoResetEvent(false);
    private static int num;

    public static async Task Main()
    {
        await Task.WhenAll(Task.Run(Method1), Task.Run(Method2));
    }

    private static void Method1()
    {
        num = 100;
        manual.Set();
        manual.WaitOne();
        num -= 1000;
        manual.Set();
    }

    private static void Method2()
    {
        manual.WaitOne();
        var into = num;
        num += into / 2;
        manual.Set();
        manual.WaitOne();
        Console.WriteLine($"final value of num {num}");
    }

1 个答案:

答案 0 :(得分:2)

是的,这是比赛条件。

Method 1 Begins
Method 2 cant start before Method 1 because it calls WaitOne in the beginning and the AutoResetEvent is not in the signaled state
Method 1 assigns num = 100
Method 1 sets AutoResetEvent. This notifies a waiting thread that an event has occurred.

其他工作将分为多种情况。

方案1:

Method 1 calls WaitOne, consumes AutoResetEvent signaled state and goes to the next line, AutoResetEvent resets.
Method 1 decreases num by 1000 (num = -900 now)
Method 1 signals AutoResetEvent
Method 2 can start cause AutoResetEvent is signlaed. AutoResetEvent resets after Method 2 getting notified.
Method 2 assigns into = num (into = -900)
Method 2 increases num by (into / 2) which makes the final result of num = -1350 (num = -900 - 450)
Method 2 signals AutoResetEvent
Method 2 consumes AutoResetEvent signaled state
Method 2 prints final value

结果为 -1350 ,并且该程序终止,因为在此方案中两个任务均已完成。

方案2:

Instead of method 1, Method 2 calls WaitOne and continues. AutoResetEvent resets.
Method 1 cant go to the next line because it is blocked by WaitOne
Method 2 assigns num to into (into = 100 now)
Method 2 increases num by into/2 (num = 100 + 50 = 150)
Method 2 sets AutoResetEvent.

在这里,方案2将分为多个方案。场景2-1和场景2-2

场景2-1:

Method 1 gets notified and decrease num by 1000 (num = 150 - 1000 = -850)
Method 1 sets AutoResetEvent.
Method 2 gets notified and prints the result.

结果为 -850 ,并且该程序终止,因为在此方案中两个任务均已完成。

方案2-2:

Method 2 gets notified and prints the result.
Method 1 will be blocked until someone somewhere set the AutoResetEvent.

结果为 150 ,并且程序没有终止,因为第一个任务尚未完成。