0

我有这个问题好几个月了。我从 entlib 4.1 升级到 5。我的应用程序正在缓存越来越多的项目。有时(有时一天三次)CPU 以 100% 的使用率挂起,但应用程序保持响应。发生这种情况时,我使用 dotTrace 获取快照,并且似乎大部分时间都花在PriorityDateComparer.Compare. 此比较器仅由 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. 以某种方式找出锁定项目的顺序,例如首先比较 (string)x 和 (string)y,然后以正确的顺序锁定它们。
  4. 其他: ...

你喜欢哪个?

4

1 回答 1

0

I changed the comparer so that it does not need to lookup the cache items:

  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;
        }
     }
  }

And in Microsoft.Practices.EnterpriseLibrary.Caching.ScavengerTask I changed the calling method accordingly from:

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

to

  private static List<CacheItem> SortItemsForScavenging(Hashtable unsortedItemsInCache)
  {
     List<CacheItem> cacheValues = new List<CacheItem>(unsortedItemsInCache.Values.Cast<CacheItem>());
     cacheValues.Sort(new PriorityDateComparer());
     return cacheValues;
  }
于 2012-07-03T20:08:53.580 回答