2011-03-01 73 views
0

我有以下代码。当部署到服务器,我得到例外,这个对象已经存在于字典。尽管如此,我做了双重锁定,同步并没有很好地发挥作用。实现这个最好的方法是什么?我怎样才能最好地锁定访问本节?我应该实现一个单例类并将方法放在那里?锁定和简单缓存

我应该锁定集合还是互斥锁?

NO我不是基于.NET 4

正如你所看到的,我想要做基于日期时间一个简单的缓存。

  // within the class. 
     IDictionary<id, MyObj> _mydict = new Dictionary<string, MyObj>(); 
     object mutex = new object; 

     //within some method comes the following 

     if (_mydict.TryGetValue(id, out myobj)) 
     { 
      DateTime now = DateTime.Now; 
      DateTime expiry = myobj.Timestamp; 
      TimeSpan span = now.Subtract(expiry); 
      if (span.Minutes 0) 
      { 
       lock (mutex) 
       { 
        myobj= DataAccess.GetMyObj(id); 
        _mydict[id] = myobj; 
       } 

       return myobj; 
      } 
      else 
      { 
       return myobj; 
      } 
     } 
     else 
     { 
      lock (mutex) 
      { 
       if (_mydict.TryGetValue(id, out myobj)) 
       { 
        return myobj; 
       } 
       else 
       { 
        lock (mutex) 
        { 
         myobj = DataAccess.GetMyObj(id); 
         _mydict[id] = myobj; 
        } 

        return myobj; 
       }      
      } 
     } 
+0

如若第二个到最后的代码行是'_myDict.Add(id,myobj)'? – 2011-03-01 01:10:28

+0

它有关系吗?我得到“这个项目已经在集合中”,这就是我为什么这样做的原因。 – DarthVader 2011-03-01 01:22:26

+0

如果我们看不到**完全**你在做什么,很难说出什么问题。 – 2011-03-01 02:20:11

回答

2

字典不是线程安全的,从阅读,你甚至称TryGetValue前应该锁定,基本上如果你使用的是字典只有一两件事可以一次触摸它

+0

老兄,你为什么要锁定整本字典查找?那么在多线程环境中使用字典有什么意义呢?如果它像单身人士一样工作的话。??????? – DarthVader 2011-03-01 01:26:10

+0

这篇文章有一个很好的解释为什么双重检查锁定不适用于Dictionary。请参阅http://stackoverflow.com/questions/2624301/how-to-show-that-the-double-checked-lock-pattern-with-dictionarys-trygetvalue-is – rsbarro 2011-03-01 03:33:12

2

如果您使用.Net 4使用ConcurrentDictionary类应该是相当有帮助的。它会照顾你的锁定。

+0

通常[System.Collections.Concurrent](http://msdn.microsoft.com/zh-cn/library/dd287108.aspx)命名空间有许多很酷的数据结构,并不是很多人使用它们。 :( – 2011-03-01 00:34:52

+0

NO IM NOT ON .NET 4 – DarthVader 2011-03-01 00:36:26

+0

应该_mydict [名称] = MyObj中;是_mydict [ID] = MyObj中;在第一个代码块应该_internetServiceProviderCache [ID] = MyObj中;?是_mydict [ID] – rsbarro 2011-03-01 00:59:18

2

只需使用ASP.Net缓存,而不是(你不需要将创建一个Web应用程序这个工作,只需添加一个参考System.Web):

void get(string key) 
{ 
    return HttpRuntime.Cache[key]; 
} 
void set(string key, object value, DateTime expires) 
{ 
    HttpRuntime.Cache.Insert(
     key, 
     value, 
     null, 
     expires, 
     Cache.NoSlidingExpiration); 
} 

简单,方便,也意味着缓存现在也有ASP.Net缓存的其他所有功能(高速缓存大小的盖子,缓存的依赖等)

+0

我同意,在System.Web命名空间中的ASP.NET缓存内置工作得很好,让你不必自己写所有这些东西。缓存应用程序块也工作得很好好。 – rsbarro 2011-03-01 01:11:43

+0

我不能使用。 – DarthVader 2011-03-01 01:12:59

+1

@ user177883为什么呢?因为2.0版本的.NET Framework的它一直一部分,是完全独立的比参考的System.Web其他的ASP.Net框架。 – Justin 2011-03-01 01:21:08

0

为什么不尝试使用列表,并插入即用类项目的值和插入该值的时间戳。然后,您可以搜索最新的时间戳和值,对结果列表进行排序,然后使用顶部项目。如果您认为合适,您可以将旧项目过期。

+0

没有名单。字典。 – DarthVader 2011-03-01 01:30:28

+0

正确的,使用字典限制你搜索一个简单的密钥。如果您使用列表_and_使用该值和时间戳进行搜索,则不必担心多次插入。你的问题就变成了如何使高速缓存中未被使用的旧条目到期。 – 2011-03-01 03:46:54