为什么锁定比Monitor.TryEnter慢得多? [英] Why is lock much slower than Monitor.TryEnter?

查看:145
本文介绍了为什么锁定比Monitor.TryEnter慢得多?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

结果



锁定:85.3微秒



Monitor.TryEnter:11.0微秒



是不是锁扩展到相同的代码



编辑:?结果与1000次迭代:
锁:103.3微秒
Monitor.TryEnter:低于20.2微秒



代码。谢谢



  [测试] 
公共无效Lock_Performance_Test()
{
const int的lockIterations = 100;

秒表csLock = Stopwatch.StartNew();
的for(int i = 0; I< lockIterations;)
{
锁(object1)
{
I ++;
}
}
csLock.Stop();

秒表csMonitor = Stopwatch.StartNew();
的for(int i = 0; I< lockIterations;)
{
如果(Monitor.TryEnter(object1,TimeSpan.FromSeconds(10)))
{
尝试
{
I ++;
}
终于
{
Monitor.Exit(object1);
}
}
}
csMonitor.Stop();

Console.WriteLine(锁定:{0:F1}微秒,csLock.Elapsed.Ticks / 10M);
Console.WriteLine(Monitor.TryEnter:{0:F1}微秒,csMonitor.Elapsed.Ticks / 10M);;
}


解决方案

我是不知道答案,但感觉指出,重要的是锁定 Monitor.TryEnter 不会功能上等同。从 Monitor.TryEnter




,这种方法获得的obj参数的
排它锁。
此方法将立即返回,
上的锁是否可用。




锁定语句类似于 Monitor.Enter ,其中确实的潜在阻塞。当然,在你的示例代码,不应该有任何阻拦的问题;但我敢打赌,因为锁定提供拦截,它确实有点更多的工作(可能)比 TryEnter 一样。






有关它的价值,我只是想在我的机器上的代码,并得到了完全不同的结果



100次迭代:结果
锁定:4.4微秒结果
Monitor.TryEnter :16.1微秒结果
Monitor.Enter :3.9微秒



100000迭代:结果
锁定:2872.5微秒结果
Monitor.TryEnter :5226.6微秒结果
Monitor.Enter :2432.9微秒



这严重损害了我最初的猜测,并表示,我的系统,锁定(其表现基本持平为 Monitor.Enter )实际上大大的优于 Monitor.TryEnter






事实上,我试图在这个VS 2010同时针对.NET 3.5和.NET 4.0,虽然结果不同,在每种情况下锁定其实并跑赢 Monitor.TryEnter



运行时版本:2.0.50727.3603



冉100次,每次迭代100000:结果
锁:279736.4 微秒结果
Monitor.TryEnter:1366751.5 微秒结果
Monitor.TryEnter(无超时):475107.3微秒结果
Monitor.Enter:332334.1微秒



运行时版本:4.0.30128.1



冉100次,每次迭代100000:结果
锁:334273.7 微秒

Monitor.TryEnter:1671363.4 微秒结果
Monitor.TryEnter(无超时):531451.8微秒结果
Monitor.Enter:316693.1微秒



(请注意,我还测试了 Monitor.TryEnter 有没有超时,因为我与马克认为,调用 TimeSpan.FromSeconds 几乎肯定放慢您的时间 Monitor.TryEnter - 并且这些测试支持 - 尽管这是奇怪的,因为在的的情况下,显然锁定还是的显著慢。)



根据这些结果,我强烈地倾向于相信您测量的执行时间以某种方式影响运行此代码的测试属性。如果不是这样,这个代码是更依赖于机器的比我预期的。


Results

Lock: 85.3 microseconds

Monitor.TryEnter: 11.0 microseconds

Isn't the lock expanded into the same code?

Edit: Results with 1000 iterations: Lock: 103.3 microseconds Monitor.TryEnter: 20.2 microseconds

Code below. Thanks

    [Test]
    public void Lock_Performance_Test()
    {
        const int lockIterations = 100;

        Stopwatch csLock = Stopwatch.StartNew();
        for (int i = 0; i < lockIterations; )
        {
            lock (object1)
            {
                i++;
            }
        }
        csLock.Stop();

        Stopwatch csMonitor = Stopwatch.StartNew();
        for (int i = 0; i < lockIterations; )
        {
            if (Monitor.TryEnter(object1, TimeSpan.FromSeconds(10)))
            {
                try
                {
                    i++;
                }
                finally
                {
                    Monitor.Exit(object1);
                }
            }
        }
        csMonitor.Stop();

        Console.WriteLine("Lock: {0:f1} microseconds", csLock.Elapsed.Ticks / 10M);
        Console.WriteLine("Monitor.TryEnter: {0:f1} microseconds", csMonitor.Elapsed.Ticks / 10M);;
    }

解决方案

I don't actually know the answer, but feel it's important to point out that lock and Monitor.TryEnter are not functionally equivalent. From the MSDN documentation on Monitor.TryEnter:

If successful, this method acquires an exclusive lock on the obj parameter. This method returns immediately, whether or not the lock is available.

The lock statement is analogous to Monitor.Enter, which does potentially block. Granted, in your example code, there shouldn't be any blocking issues; but I would wager that since lock provides blocking, it does a little more work (potentially) than TryEnter does.


For what it's worth, I just tried your code on my machine and got completely different results:

100 iterations:
lock: 4.4 microseconds
Monitor.TryEnter: 16.1 microseconds
Monitor.Enter: 3.9 microseconds

100000 iterations:
lock: 2872.5 microseconds
Monitor.TryEnter: 5226.6 microseconds
Monitor.Enter: 2432.9 microseconds

This seriously undermines my initial guess and shows that, on my system, lock (which performs about the same as Monitor.Enter) actually drastically outperforms Monitor.TryEnter.


Indeed, I attempted this in VS 2010 targeting both .NET 3.5 and .NET 4.0 and, though the results were different, in each case lock did in fact outperform Monitor.TryEnter:

Runtime version: 2.0.50727.3603

Ran 100 times, 100000 iterations each time:
Lock: 279736.4 microseconds
Monitor.TryEnter: 1366751.5 microseconds
Monitor.TryEnter (no timeout): 475107.3 microseconds
Monitor.Enter: 332334.1 microseconds

Runtime version: 4.0.30128.1

Ran 100 times, 100000 iterations each time:
Lock: 334273.7 microseconds
Monitor.TryEnter: 1671363.4 microseconds
Monitor.TryEnter (no timeout): 531451.8 microseconds
Monitor.Enter: 316693.1 microseconds

(Notice I also tested Monitor.TryEnter with no timeout, as I agreed with Marc that calling TimeSpan.FromSeconds was almost certainly slowing down your times for Monitor.TryEnter--and these tests support that--though it's strange, since in your case apparently lock is still significantly slower.)

Based on these results I am strongly inclined to believe that your measured execution times are somehow affected by running this code with the Test attribute. Either that or this code is far more machine-dependent than I would have expected.

这篇关于为什么锁定比Monitor.TryEnter慢得多?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆