鉴于代码:
private static readonly object GetMyObjLock = new object();
public static MyObject GetFromCache()
{
var key = "MyObj";
var cache = HttpContext.Current.Cache;
if (cache[key] == null)
{
lock (GetMyObjLock)
{
if (cache[key] == null)
{
cache.Add(key,
new MyObject(), null,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.Normal, null);
}
}
}
return (MyObject) cache[key];
}
电话:
var myObj = GetFromCache();
myObj.PerformMethod();
使用某些代码侦听另一个执行此操作的线程:
if(message == "invalidate")
{
Httpcontext.Current.Cache.Remove("MyObj");
}
两个问题:
PerformMethod
会一直完成吗?myObj
方法和null
通话之间GetFromCache()
是否有机会等同PerformMethod
?答案 0 :(得分:2)
考虑线程的这个时间:
主题1:
var myObj = GetFromCache();
public static MyObject GetFromCache()
{
var key = "MyObj";
var cache = HttpContext.Current.Cache;
if (cache[key] == null)
{
lock (GetMyObjLock)
{
if (cache[key] == null)
{
cache.Add(key,
new MyObject(), null,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.Normal, null);
}
}
}
主题2:
if(message == "invalidate")
{
Httpcontext.Current.Cache.Remove("MyObj");
}
主题1:
return (MyObject) cache[key];
}
myObj.PerformMethod();
它将破坏您的实施
可能的解决方法是将new MyObject()
存储在局部变量中,然后将其添加到缓存中,然后返回局部变量。这将有效,因为它是一个强有力的参考:
var myobject = new MyObject();
cache.Add(key,
myobject, null,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.Normal, null);
return myobject;
答案 1 :(得分:1)
修复它的方法是使用null
函数的输出来查看您添加的项是否实际添加到缓存中,如果它已经存在,它将返回前一个实例,如果它不存在它返回private static readonly object GetMyObjLock = new object();
public static MyObject GetFromCache()
{
var key = "MyObj";
var cache = HttpContext.Current.Cache;
MyObject result;
//Try to pull from the cache.
result = (MyObject)cache[key];
if(result == null)
{
//This lock is used to make sure the MyObject constructor is not called
// concurrently, it is not for thread safe access to the cache.
lock(GetMyObjLock)
{
//Check to see if anyone made a new object while we where waiting.
result = (MyObject)cache[key];
if(result == null)
{
var newObject = new MyObject();
//Try to add to cache, if the object was already added by someone who
// does not use the GetMyObjLock this function returns the previously
// added instance.
result = (MyObject)cache.Add(key,
newObject, null,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.Normal, null);
//If result is null then we successfully added a new
// item, assign it to result.
if(result == null)
result = newObject;
}
}
}
}
return result;
}
。当它返回null时,您只需将传入的对象设置为第二个参数作为从函数返回的结果。
{{1}}