예제 #1
0
            private void AcquireLock(InstanceScopedStripedLockProvider provider, string key)
            {
                // Monitor.Enter and Monitor.Exit are tied to a specific thread and are
                //  slower than this spin lock, which does not care about threads and will execute very
                //  quickly, regardless of lock contention
                // https://stackoverflow.com/questions/11001760/monitor-enter-and-monitor-exit-in-different-threads

                // make unchecked just in case compiler is doing extra checks in the int to uint cast
                unchecked
                {
                    // Get a hash based on the key, use this to lock on a specific int in the array. The array is designed
                    // to be small enough to not use very much memory, but large enough to avoid collisions.
                    // Even if there is a collision, it will be resolved very quickly.
                    _hash = (uint)(key ?? string.Empty).GetHashCode() % (uint)provider.keyLocks.Length;
                }

                // To get the lock, we must change the int at hash index from a 0 to a 1. If the value is
                //  already a 1, we don't get the lock. The return value must be 0 (the original value of the int).
                // it is very unlikely to have any contention here, but if so, the spin cycle should be very short.
                // Parameter index 1 (value of 1) is the value to change to if the existing value (Parameter index 2) is 0.
                while (Interlocked.CompareExchange(ref provider.keyLocks[_hash], 1, 0) == 1)
                {
                    // give up a clock cycle, we want to get back and try to get the lock again very quickly
                    System.Threading.Thread.Yield();
                }

                _lockProvider = provider;
            }
예제 #2
0
 public InstanceScopedStripedLockReleaser(InstanceScopedStripedLockProvider provider, string key)
 {
     AcquireLock(provider, key);
 }