Why is lock much slower than Monitor.TryEnter?

前端 未结 5 573
囚心锁ツ
囚心锁ツ 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:23

    If you need speed doing this, then SpinLock is a far better choice in my experience.

    public class DisposableSpinLock : IDisposable {
        private SpinLock mylock;
        private bool isLocked;
    
        public DisposableSpinLock( SpinLock thelock ) {
            this.mylock = thelock;
            mylock.Enter( ref isLocked );
        }
    
        public DisposableSpinLock(  SpinLock thelock, bool tryLock) {
            this.mylock = thelock;
            if( tryLock ) {
                mylock.TryEnter( ref isLocked );
            } else {
                mylock.Enter( ref isLocked );
            }
        }
    
        public bool IsLocked { get { return isLocked; } }
    
        public void Dispose() {
            Dispose( true );
            GC.SuppressFinalize( this );
        }
    
        protected virtual void Dispose( bool disposing ) {
            if( disposing ) {
                if( isLocked ) {
                    mylock.Exit();
                }
            }
        }
    }
    

    Is a nice useful way to get things to work "automatically" in abort and exception cases.

    You can just create a SpinLock instead of the "lock" object, and then use:

    using( new DisposableSpinLock( myLock ) ) {
         // Under lock and key...
    }
    

    This allows you to get the same single line of code that lock() provides while also dealing with the required try {} finally{} behavior and have a bit more control over what happens to cleanup the object.

    I also have support for the "try" case which would be written using code blocks with an extra if statement inside:

    using( theLock = new DisposableSpinLock( myLock, true ) ) {
        if( theLock.IsLocked ) {
            // Under Lock and Key
        }
    }
    

    SpinLock is not not CPU friendly for highly contended locks because of the added CPU use of SpinLock in that situation, but for the locks that are pretty much synchronized and just need occasionally locking for outside references or occasional second thread access, this is a big win.

    Yes, this is not gorgeous, but for me, SpinLocks have made everything that I have for lightly contended locks much more performant.

    http://www.adammil.net/blog/v111_Creating_High-Performance_Locks_and_Lock-free_Code_for_NET_.html is a good look at spin locks and locking overall.

提交回复
热议问题