diff --git a/LazyCache/CachingService.cs b/LazyCache/CachingService.cs index df091de..00fa01f 100644 --- a/LazyCache/CachingService.cs +++ b/LazyCache/CachingService.cs @@ -12,7 +12,7 @@ public class CachingService : IAppCache { private readonly Lazy cacheProvider; - private readonly int[] keyLocks; + private readonly object[] keyLocks; public CachingService() : this(DefaultCacheProvider) { @@ -22,7 +22,8 @@ public CachingService(Lazy cacheProvider) { this.cacheProvider = cacheProvider ?? throw new ArgumentNullException(nameof(cacheProvider)); var lockCount = Math.Max(Environment.ProcessorCount * 8, 32); - keyLocks = new int[lockCount]; + keyLocks = new object[lockCount]; + for (i = 0; i < keyLocks.Length; i++) keyLocks[i] = new object(); } public CachingService(Func cacheProviderFactory) @@ -30,8 +31,8 @@ public CachingService(Func cacheProviderFactory) if (cacheProviderFactory == null) throw new ArgumentNullException(nameof(cacheProviderFactory)); cacheProvider = new Lazy(cacheProviderFactory); var lockCount = Math.Max(Environment.ProcessorCount * 8, 32); - keyLocks = new int[lockCount]; - + keyLocks = new object[lockCount]; + for (i = 0; i < keyLocks.Length; i++) keyLocks[i] = new object(); } public CachingService(ICacheProvider cache) : this(() => cache) @@ -117,16 +118,10 @@ object CacheFactory(ICacheEntry entry) => // acquire lock per key uint hash = (uint)key.GetHashCode() % (uint)keyLocks.Length; - while (Interlocked.CompareExchange(ref keyLocks[hash], 1, 0) == 1) { Thread.Yield(); } - - try + lock (keyLocks[hash]) { cacheItem = CacheProvider.GetOrCreate(key, policy, CacheFactory); } - finally - { - keyLocks[hash] = 0; - } try { @@ -139,16 +134,10 @@ object CacheFactory(ICacheEntry entry) => // acquire lock again hash = (uint)key.GetHashCode() % (uint)keyLocks.Length; - while (Interlocked.CompareExchange(ref keyLocks[hash], 1, 0) == 1) { Thread.Yield(); } - - try + lock (keyLocks[hash]) { cacheItem = CacheProvider.GetOrCreate(key, CacheFactory); } - finally - { - keyLocks[hash] = 0; - } result = GetValueFromLazy(cacheItem, out _ /* we just evicted so type change cannot happen this time */); } @@ -195,10 +184,6 @@ public virtual async Task GetOrAddAsync(string key, Func new AsyncLazy(async () => { @@ -208,14 +193,12 @@ object CacheFactory(ICacheEntry entry) => return result; }); - try + // acquire lock + uint hash = (uint)key.GetHashCode() % (uint)keyLocks.Length; + lock (keyLocks[hash]) { cacheItem = CacheProvider.GetOrCreate(key, policy, CacheFactory); } - finally - { - keyLocks[hash] = 0; - } try { @@ -228,16 +211,10 @@ object CacheFactory(ICacheEntry entry) => // acquire lock hash = (uint)key.GetHashCode() % (uint)keyLocks.Length; - while (Interlocked.CompareExchange(ref keyLocks[hash], 1, 0) == 1) { Thread.Yield(); } - - try + lock (keyLocks[hash]) { cacheItem = CacheProvider.GetOrCreate(key, CacheFactory); } - finally - { - keyLocks[hash] = 0; - } result = GetValueFromAsyncLazy(cacheItem, out _ /* we just evicted so type change cannot happen this time */); } @@ -341,4 +318,4 @@ protected virtual void ValidateKey(string key) throw new ArgumentOutOfRangeException(nameof(key), "Cache keys cannot be empty or whitespace"); } } -} \ No newline at end of file +}