锁定基本类型

时间:2015-10-13 08:45:21

标签: 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);
    }
}

我认为这应该不起作用,因为我正在对整数值进行同步。 First Boxing,然后是Unboxing,我应该得到一个System.Threading.SynchronizationLockException,因为缺少同步块根(我知道这是特定于引用类型)。 我不会欺骗自己,即使这适用于几次迭代,它也不是真的同步..所以,考虑到增量操作的非原子属性..我不会得到确定性的结果..我知道此

事实上,当我摆脱Thead.Sleep并对任务进行等待时......异常就会到位。

Task.Factory.StartNew(() =>
 {
       MultithreadedMethod();
 }).Wait();

我认为应该抛出异常:Monitor.Exit(sync)

但是有什么能吸引它?

更新1:pic已添加。

enter image description here

2 个答案:

答案 0 :(得分:6)

  

但是有什么能吸引它?

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秒睡眠后发生。

答案 1 :(得分:3)

当我运行你的代码时,我在输出窗口中看到:

  

抛出异常:&#39; System.Threading.SynchronizationLockException&#39;在ConsoleApplication5.exe中

我猜你没有捕获来自任务的异常(并且当你的IDE未被处理时你的IDE没有被设置为中断)。试试这个:

,而不是沉睡线程
List<Task> tasks = new List<Task>();
for (int i = 0; i < 21000; i++)
{
    tasks.Add(Task.Factory.StartNew(() =>
    {
        MultithreadedMethod();
    }));
}

Task.WaitAll(tasks.ToArray());

WaitAll将显示例外情况。