2016-12-07 81 views
2

我有多個線程要求必須通過網絡加載的數據。 爲了減少網絡流量和更快的響應速度,我想要緩存通常需要的數據。我也想限制Cache的數據大小。如何實現具有數據大小限制的緩存?

我的類看起來是這樣的:

public class DataProvider 
{ 
    private ConcurrentDictionary<string, byte[]> dataCache; 
    private int dataCacheSize; 
    private int maxDataCacheSize; 
    private object dataCacheSizeLockObj = new object(); 

    public DataProvider(int maxCacheSize) 
    { 
     maxDataCacheSize = maxCacheSize; 
     dataCache = new ConcurrentDictionary<string,byte[]>(); 
    } 

    public byte[] GetData(string key) 
    { 
     byte[] retVal; 

     if (dataCache.ContainsKey(key)) 
     { 
      retVal = dataCache[key]; 
     } 
     else 
     { 
      retVal = ... // get data from somewhere else 

      if (dataCacheSize + retVal.Length <= maxDataCacheSize) 
      { 
       lock (dataCacheSizeLockObj) 
       { 
        dataCacheSize += retVal.Length; 
       } 
       dataCache[key] = retVal; 
      } 
     } 
     return retVal; 
    } 
} 

我的問題是:我該如何確保,即dataCacheSize始終具有正確的價值?如果兩個線程同時請求相同的未緩存數據,則它們都會將它們的數據寫入緩存中,這是沒有問題的,因爲數據是相同的,第二個線程只會用相同的數據覆蓋緩存的數據。但是,我怎麼知道,如果它被覆蓋或者不能兩次計算它的大小?

它也可能發生,這兩個線程都在導致數據高速緩存大小大於允許的最大值,同時將數據添加...

是否有完成這個任務不增加複雜的鎖定機制的一個優雅的方式?

+4

而不是試圖「推出自己的」緩存,看看System.Runtime.Caching.MemoryCache。 https://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache(v=vs.110).aspx – Kevin

+0

好的,MemoryCache似乎做的工作。我必須檢查它的緩存管理選項。你想回答這個問題嗎?我無法接受評論。 – Ben

+0

已發佈的答案。謝謝 – Kevin

回答

1

,而不是試圖「你自己卷」緩存,看看System.Runtime.Caching。的MemoryCache。見上面的評論。

0

既然你更新dataCacheSize內鎖,你可以查看這裏是否會保持正確的:

if (dataCacheSize + retVal.Length <= maxDataCacheSize) 
{ 
    lock (dataCacheSizeLockObj) 
    { 
     if (dataCacheSize + retVal.Length > maxDataCacheSize) 
     { 
      return retVal; 
     } 
     dataCacheSize += retVal.Length; 
    } 
    byte[] oldVal = dataCache.GetOrAdd(key, retVal); 
    if (oldVal != retVal) 
    { 
     // retVal wasn't actually added 
     lock (dataCacheSizeLockObj) 
     { 
      dataCacheSize -= retVal.Length; 
     } 
    } 
} 
+0

這是行不通的。當2個線程同時添加相同的條目時,它仍會將retVal.Length兩次添加到dataCacheSize。 – Ben

+0

可以使用'GetOrAdd'方法而不是'dataCache [key] = retVal'來解決這個競爭條件(我更新了答案)。但是最好使用System.Runtime.Caching.MemoryCache。 –