在该对象的函数调用期间,是否可以删除缓存中的对象?

时间:2016-11-14 16:53:10

标签: c# caching thread-safety

鉴于代码:

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

2 个答案:

答案 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}}