我想检查一些锁定行为,但我无法理解:
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
Task.Factory.StartNew(() =>
{
MultithreadedMethod();
});
}
Thread.Sleep(2000);
Console.WriteLine(count);
}
static int count = 0;
private static readonly int sync = 5;
public static void MultithreadedMethod()
{
if (Monitor.TryEnter(sync))
{
count++;
Monitor.Exit(sync);
}
}
我认为这应该行不通,因为我正在对一个整数值进行同步。首先装箱,然后拆箱,我应该得到一个 System.Threading.SynchronizationLockException 因为缺少同步块(synchronized block)根(我知道这是特定于引用类型)。 我不会自欺欺人,即使这适用于几次迭代,它也不是真正同步的..所以,考虑到增量操作的非原子属性..我不会得到确定性的结果..我知道这个。
的确,当我摆脱那个 Thead.Sleep 并在任务上放置一个 Wait 时.. 异常出现了。
Task.Factory.StartNew(() =>
{
MultithreadedMethod();
}).Wait();
我认为这里应该抛出异常:Monitor.Exit(sync)
但是什么捕获了它?
更新 1:添加了图片。
最佳答案
but what catches it?
在 Task
对象中抛出的异常在该 Task
中被隐式捕获。除非您在返回的任务上访问 Task.Exception
或 Task.Wait/Task.Result
属性,或 await
,否则异常将被吞没你将看不到它。这就是为什么使用 Wait
传播异常并且您可以在控制台中看到它。如果您使用 Task.WaitAll
等待所有任务完成,也会发生同样的情况。
如果您不使用这些中的任何一个,您仍然可以通过注册到 TaskScheduler.UnobservedTaskException
查看异常。 :
static void Main(string[] args)
{
TaskScheduler.UnobservedTaskException += (s,e) => Console.WriteLine(e.Exception);
for (int i = 0; i < 10; i++)
{
Task.Factory.StartNew(() =>
{
MultithreadedMethod();
});
}
Thread.Sleep(2000);
Console.WriteLine(count);
}
产量:
请注意这段代码仍然存在竞争条件,因为我们实际上并没有等待任何结果的到来,这可能不会在休眠 2 秒后发生。
关于c# - 锁定原始类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33098051/