为什么锁定比Monitor.TryEnter慢得多? [英] Why is lock much slower than 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
一个MSDN文档>:
,这种方法获得的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 对code>)实际上大大的优于的
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
andMonitor.TryEnter
are not functionally equivalent. From the MSDN documentation onMonitor.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 toMonitor.Enter
, which does potentially block. Granted, in your example code, there shouldn't be any blocking issues; but I would wager that sincelock
provides blocking, it does a little more work (potentially) thanTryEnter
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 microseconds100000 iterations:
lock
: 2872.5 microseconds
Monitor.TryEnter
: 5226.6 microseconds
Monitor.Enter
: 2432.9 microsecondsThis seriously undermines my initial guess and shows that, on my system,
lock
(which performs about the same asMonitor.Enter
) actually drastically outperformsMonitor.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 outperformMonitor.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 microsecondsRuntime 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 callingTimeSpan.FromSeconds
was almost certainly slowing down your times forMonitor.TryEnter
--and these tests support that--though it's strange, since in your case apparentlylock
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屋!