c# - 锁定原始类型

标签 c# multithreading

我想检查一些锁定行为,但我无法理解:

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:添加了图片。

enter image description here

最佳答案

but what catches it?

Task 对象中抛出的异常在该 Task 中被隐式捕获。除非您在返回的任务上访问 Task.ExceptionTask.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);
}

产量:

Unobserved task exception

请注意这段代码仍然存在竞争条件,因为我们实际上并没有等待任何结果的到来,这可能不会在休眠 2 秒后发生。

关于c# - 锁定原始类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33098051/

相关文章:

c# - 使用一次数据库调用加载业务对象层次结构

c# - CSS 事件按钮

java - ExecutorService,如何在不阻塞主线程的情况下知道所有线程何时完成?

multithreading - Scala - 可变线程安全集合

java - executorService.shutdownNow() 不会停止线程

java - 了解同步块(synchronized block)和内在锁

c# - Web API 异常包装器

c# - 迭代直到达到 int.MaxValue

C# 字符串操作

c# - 将 GUI 值传递给 backgroundworker 的正确方法?