Why is lock much slower than Monitor.TryEnter?

前端 未结 5 683
囚心锁ツ
囚心锁ツ 2021-02-07 03:06

Results

Lock: 85.3 microseconds

Monitor.TryEnter: 11.0 microseconds

Isn\'t the lock expanded into the same code?

Edit: Results with 1000 iteratio

5条回答
  •  半阙折子戏
    2021-02-07 03:25

    100 is far too few, and running in a test framework may skew things. It is also possibly (see comments) related to any additional cost associated with the first lock against an object; try:

    • locking once outside the loop first
    • doing lots more iterations
    • in a console exe, at the command line, in release mode

    Also, note that in 4.0 lock is not Monitor.Enter(object) - so expect different results in 4.0.

    But I get:

    lock: 3548ms
    Monitor.TryEnter: 7008ms
    Monitor.TryEnter (2): 2947ms
    Monitor.Enter: 2906ms
    

    From the test rig:

    using System;
    using System.Diagnostics;
    using System.Threading;
    static class Program {
        static void Main()
        {
            const int lockIterations = 50000000;
            object object1 = new object();
            lock (object1) { Console.WriteLine("First one has to pay an extra toll"); }
            Stopwatch csLock = Stopwatch.StartNew();
            for (int i = 0; i < lockIterations; ) {
                lock (object1) { i++; }
            }
            csLock.Stop();
            Console.WriteLine("lock: " + csLock.ElapsedMilliseconds + "ms");
    
            Stopwatch csMonitorTryEnter = Stopwatch.StartNew();
            for (int i = 0; i < lockIterations; ) {
                if (Monitor.TryEnter(object1, TimeSpan.FromSeconds(10))) {
                    try { i++; } finally { Monitor.Exit(object1); }
                }
            }
            csMonitorTryEnter.Stop();
            Console.WriteLine("Monitor.TryEnter: " + csMonitorTryEnter.ElapsedMilliseconds + "ms");
    
            csMonitorTryEnter = Stopwatch.StartNew();
            for (int i = 0; i < lockIterations; ) {
                if (Monitor.TryEnter(object1, 10000)) {
                    try { i++; } finally { Monitor.Exit(object1); }
                }
            }
            csMonitorTryEnter.Stop();
            Console.WriteLine("Monitor.TryEnter (2): " + csMonitorTryEnter.ElapsedMilliseconds + "ms");
    
            Stopwatch csMonitorEnter = Stopwatch.StartNew();
            for (int i = 0; i < lockIterations; ) {
                Monitor.Enter(object1);
                try { i++; } finally { Monitor.Exit(object1); }
            }
            csMonitorEnter.Stop();
            Console.WriteLine("Monitor.Enter: " + csMonitorEnter.ElapsedMilliseconds + "ms");
        }
    }
    

提交回复
热议问题