पूरे कैश उदाहरण को लॉक करने की कोई आवश्यकता नहीं है, बल्कि हमें केवल उस विशिष्ट कुंजी को लॉक करने की आवश्यकता है जिसे आप डाल रहे हैं। पुरुष शौचालय का उपयोग करते समय महिला शौचालय की पहुंच को ब्लॉक करने की कोई आवश्यकता नहीं है :)
नीचे दिया गया कार्यान्वयन एक समवर्ती शब्दकोश का उपयोग करके विशिष्ट कैश-कीज़ को लॉक करने की अनुमति देता है। इस तरह से आप GetOrAdd () एक ही समय में दो अलग-अलग कुंजी के लिए चला सकते हैं - लेकिन एक ही समय में एक ही कुंजी के लिए नहीं।
using System;
using System.Collections.Concurrent;
using System.Web.Caching;
public static class CacheExtensions
{
private static ConcurrentDictionary<string, object> keyLocks = new ConcurrentDictionary<string, object>();
public static T GetOrAdd<T>(this Cache cache, string key, int durationInSeconds, Func<T> factory)
where T : class
{
var value = cache.Get(key);
if (value == null)
{
lock (keyLocks.GetOrAdd(key, new object()))
{
value = cache.Get(key);
if (value == null && (value = factory()) != null)
{
cache.Insert(
key: key,
value: value,
dependencies: null,
absoluteExpiration: DateTime.Now.AddSeconds(durationInSeconds),
slidingExpiration: Cache.NoSlidingExpiration,
priority: CacheItemPriority.Default,
onRemoveCallback: null);
}
keyLocks.TryRemove(key, out object locker);
}
}
return value as T;
}
}