EntLib 5缓存 - 怀疑死锁 - cpu挂起100%

时间:2012-06-22 09:22:21

标签: caching deadlock cpu-usage enterprise-library-5

我现在已经有好几个月了。我从entlib 4.1升级到5.我的应用程序正在缓存越来越多的项目。有时(有时一天三次)CPU会以100%的使用率挂起,但应用程序会保持响应。当发生这种情况时,我使用dotTrace来获取快照,并且似乎大部分时间都花费在PriorityDateComparer.Compare上。此Comparer仅由System.Collections.SortedList的构造函数使用,并包含此正文:

public int Compare(object x, object y)
{
   CacheItem leftCacheItem = (CacheItem)unsortedItems[(string)x];
   CacheItem rightCacheItem = (CacheItem)unsortedItems[(string)y];

   lock (rightCacheItem)
   {
         lock (leftCacheItem)
         {
            if (rightCacheItem == null && leftCacheItem == null)
            {
               return 0;
            }
            if (leftCacheItem == null)
            {
               return -1;
            }
            if (rightCacheItem == null)
            {
               return 1;
            }

            return leftCacheItem.ScavengingPriority == rightCacheItem.ScavengingPriority
               ? leftCacheItem.LastAccessedTime.CompareTo(rightCacheItem.LastAccessedTime)
               : leftCacheItem.ScavengingPriority - rightCacheItem.ScavengingPriority;
         }
   }
}

问题1:我们能确定两个缓存项始终以相同的顺序锁定吗?如果我检查SortedList的实现,我不这么认为。

问题2:如果我的第一个问题的答案是那么我们如何解决这个问题?我看到了一些可能性:

  1. 取消锁定并确保仅使用一个线程。
  2. 将一个锁定放在unsortedItems集合上,而不是放在cacheItems上。
  3. 以某种方式确定锁定项目的顺序,例如首先比较(字符串)x和(字符串)y,然后按正确的顺序锁定它们。
  4. 其他:......
  5. 你更喜欢什么?

1 个答案:

答案 0 :(得分:0)

我更改了比较器,因此无需查找缓存项:

  int IComparer<CacheItem>.Compare(CacheItem leftCacheItem, CacheItem rightCacheItem)
  {
     lock (rightCacheItem)
     {
        lock (leftCacheItem)
        {
           if (rightCacheItem == null && leftCacheItem == null)
           {
              return 0;
           }
           if (leftCacheItem == null)
           {
              return -1;
           }
           if (rightCacheItem == null)
           {
              return 1;
           }

           return leftCacheItem.ScavengingPriority == rightCacheItem.ScavengingPriority
               ? leftCacheItem.LastAccessedTime.CompareTo(rightCacheItem.LastAccessedTime)
               : leftCacheItem.ScavengingPriority - rightCacheItem.ScavengingPriority;
        }
     }
  }

Microsoft.Practices.EnterpriseLibrary.Caching.ScavengerTask中,我相应地改变了调用方法:

  private static SortedList SortItemsForScavenging(Hashtable unsortedItemsInCache)
  {
     return new SortedList(unsortedItemsInCache, new PriorityDateComparer(unsortedItemsInCache));
  }

  private static List<CacheItem> SortItemsForScavenging(Hashtable unsortedItemsInCache)
  {
     List<CacheItem> cacheValues = new List<CacheItem>(unsortedItemsInCache.Values.Cast<CacheItem>());
     cacheValues.Sort(new PriorityDateComparer());
     return cacheValues;
  }