我正在试验.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}");
}
答案 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 ,并且程序没有终止,因为第一个任务尚未完成。