0

If I understood correctly, then the concurrent collections create a snapshot as a source for the Enumerator used in a foreach loop, which requires locking.

Do they cache the snapshots or lock every time? Does this have a potential performance impact? I'm sceptical about micro-measurements, because they so easily lead to false conclusions and am trying to understand the inner workings.

Thanks!

mike
  • 1,627
  • 1
  • 14
  • 37
  • 1
    The [reference documentation](https://referencesource.microsoft.com/#mscorlib/system/Collections/Concurrent/ConcurrentDictionary.cs,780) for `GetEnumerator` on `ConcurrentDictionary` states that it does not snapshot or lock, and while it's safe to read the data may be mutated while you have it. Which concurrent collections are you referring to specifically? – Jonathon Chase Nov 26 '18 at 23:22

1 Answers1

1

No, it doesn't appear to cache. Here's the code from ConcurrentBag<T>:

public IEnumerator<T> GetEnumerator()
{
    if (m_headList != null)
    {
        bool lockTaken = false;
        try
        {
            FreezeBag(ref lockTaken);
            return ToList().GetEnumerator();
        }
        finally
        {
            UnfreezeBag(lockTaken);
        }
    }
    return new List<T>().GetEnumerator();
}

private List<T> ToList()
{
    List<T> list = new List<T>();
    for (ThreadLocalList threadLocalList = m_headList; threadLocalList != null; threadLocalList = threadLocalList.m_nextList)
    {
        for (Node node = threadLocalList.m_head; node != null; node = node.m_next)
        {
            list.Add(node.m_value);
        }
    }
    return list;
}
Enigmativity
  • 113,464
  • 11
  • 89
  • 172