ConcurrentDictionary在删除时似乎没有标记GC的元素

时间:2014-02-18 22:15:22

标签: c# collections concurrency .net-4.0 garbage-collection

我惊讶地发现我的应用程序内存占用不断增长 - 运行的时间越长,消耗的内存就越多。因此,windbg的一些魔力让我根据ConcurrentDictionary向我的小LRU缓存指出了一个问题。 CD有很多好处,对我来说非常酷(其中一个是它的数据永远不会在LOH中结束)。 TryAddTryRemove是用于添加和逐出项目的两种方法。一些旧元素的!gcroot将我带回了我的缓存。对ILSpy进行的一些调查使我得出了这样的结论:

TryRemove 确实删除了一个元素。它只是改变链表指针以跳过从不将数组元素的值赋给null。这可以防止GC收集旧的被驱逐的物体。

真的?这是一个已知的问题吗?如果是这样,我唯一的选择是TryUpdate(key, null)然后是TryRemove(key)?如果是这样,那么我必须锁定ConcurrentDictionary访问,这是矛盾的。

这是ILSpy转储:

// System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>
private bool TryRemoveInternal(TKey key, out TValue value, bool matchValue, TValue oldValue)
{
    while (true)
    {
        ConcurrentDictionary<TKey, TValue>.Tables tables = this.m_tables;
        int num;
        int num2;
        this.GetBucketAndLockNo(this.m_comparer.GetHashCode(key), out num, out num2, tables.m_buckets.Length, tables.m_locks.Length);
        lock (tables.m_locks[num2])
        {
            if (tables != this.m_tables)
            {
                continue;
            }
            ConcurrentDictionary<TKey, TValue>.Node node = null;
            ConcurrentDictionary<TKey, TValue>.Node node2 = tables.m_buckets[num];
            while (node2 != null)
            {
                if (this.m_comparer.Equals(node2.m_key, key))
                {
                    bool result;
                    if (matchValue && !EqualityComparer<TValue>.Default.Equals(oldValue, node2.m_value))
                    {
                        value = default(TValue);
                        result = false;
                        return result;
                    }
                    if (node == null)
                    {
                        Volatile.Write<ConcurrentDictionary<TKey, TValue>.Node>(ref tables.m_buckets[num], node2.m_next);
                    }
                    else
                    {
                        node.m_next = node2.m_next;
                    }
                    value = node2.m_value;
                    tables.m_countPerLock[num2]--;
                    result = true;
                    return result;
                }
                else
                {
                    node = node2;
                    node2 = node2.m_next;
                }
            }
        }
        break;
    }
    value = default(TValue);
    return false;
}

0 个答案:

没有答案
相关问题