ConcurrentBag <T>实现中是否存在内存泄漏?

Alo*_*aus 13 .net c# task-parallel-library base-class-library

可能重复:
ConcurrentBag中可能的内存泄漏?

EDIT1:

实际的问题是.你能证实这一点,还是我的样本错了,我错过了一些明显的东西?

我认为ConcurrentBag是一个简单的替代无序列表.但是我错了.ConcurrentBag确实将自己作为ThreadLocal添加到创建线程,这基本上会导致内存泄漏.

   class Program
    {
        static void Main(string[] args)
        {
            var start = GC.GetTotalMemory(true);
            new Program().Start(args);
            Console.WriteLine("Diff: {0:N0} bytes", GC.GetTotalMemory(true) - start);
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            Thread.Sleep(5000);
        }

        private void Start(string[] args)
        {
            for (int i = 0; i < 1000; i++)
            { 
                var bag = new ConcurrentBag<byte>();
                bag.Add(1);
                byte by;
                while (bag.TryTake(out by)) ;
            }
        }
Run Code Online (Sandbox Code Playgroud)

我可以制作Diff 250 KB或100 GB,具体取决于我添加到包中的数据量.数据和包包都消失了.

当我用Windbg打破这个时,我做了一个!DumpHeap -type Concurrent

....

000007ff00046858        1           24 System.Threading.ThreadLocal`1+GenericHolder`3[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System],[System.Threading.ThreadLocal`1+C0[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]], mscorlib],[System.Threading.ThreadLocal`1+C0[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]], mscorlib],[System.Threading.ThreadLocal`1+C0[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]], mscorlib]]
000007feed812648        2           64 System.Collections.Concurrent.ConcurrentStack`1[[System.Int32, mscorlib]]
000007feece41528        1          112 System.Collections.Concurrent.CDSCollectionETWBCLProvider
000007ff000469e0     1000        32000 System.Threading.ThreadLocal`1+Boxed[[System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]], System]]
000007feed815900     1000        32000 System.Collections.Concurrent.ConcurrentStack`1+Node[[System.Int32, mscorlib]]
000007ff00045530     1000        72000 System.Collections.Concurrent.ConcurrentBag`1+ThreadLocalList[[System.Byte, mscorlib]]
Run Code Online (Sandbox Code Playgroud)

当我创建一个空的ConcurrentBag让一些工作线程向它添加数据时ConcurrentBag及其数据将在那里,只要创建线程仍然存在.

这样我就得到了几GB的内存泄漏.我通过使用List和锁来"修复"这个问题.ConcurrentBag可能很快,但它对于具有相同对象生存期的List的简单替换是无用的.

如果我在主线程上创建一个ConcurrentBag,只要线程处于活动状态,我就会保留它.这不是我所期望的,它可能会导致重大痛苦.

dar*_*yal 3

你说得对,ConcurrentBag 创建了一个 ThreadLocal 副本,实际上它们针对同一线程读取数据并将数据写入包的场景进行了优化:“...ConcurrentBag 是一个线程安全的包实现,针对相同线程读取数据并将数据写入包的场景进行了优化”线程将生成和消耗存储在包中的数据。”

另一方面,我在这里没有看到奇怪的行为;线程存活并且并发包存活。当线程完成时,GC 将完成它的工作。