2011-03-01 51 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