2016-12-07 63 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。 –