C#中的弱引用

弱引用保持的是一个GC“不可见”的引用,是指弱引用不会增加对象的引用计数,也不会阻止垃圾回收器对该对象进行回收。因此,弱引用的目标对象可以被垃圾回收器回收,而弱引用本身不会对垃圾回收造成任何影响。

弱引用的原理是,在堆上分配的每个对象都有一个头部信息,用于存储对象的类型信息、对象的大小等信息。在头部信息中,还会有一个标志位用于表示对象是否被引用。当一个对象被创建时,该标志位为“未引用”。当该对象被弱引用引用时,该标志位不会变为“已引用”,即该对象仍然会被当做未引用的对象进行处理。被强引用后,会被标记为”已引用“,当所有的强引用都消失时,该标志位会变为“未引用”,即该对象已经没有任何强引用指向它,标记的工作由GC来完成。

在垃圾回收时,GC会根据标记-清除算法对堆中的对象进行扫描和标记,标记所有仍然被引用的对象,然后回收所有未被标记的对象。对于被弱引用引用的对象,由于弱引用不会增加对象的引用计数,也不会阻止垃圾回收器回收该对象,因此在回收时,该对象会被当做未被引用的对象进行处理,然后被回收。

总之,弱引用保持的是一个GC“不可见”的引用,即弱引用不会影响垃圾回收器对目标对象的回收,因此可以用于实现一些场景,例如缓存、对象池等场景,避免长时间占用内存或造成内存泄漏。

var sb = new StringBuilder("weak");
            Console.WriteLine("before GC");
            Console.WriteLine(sb);
            GC.Collect();//强制垃圾回收
            Console.WriteLine("after GC");
            Console.WriteLine(sb);
            Console.ReadLine();

output

before GC
weak
after GC
weak

以下代码在release模式下:

var sb = new StringBuilder("weak");
            var weak = new WeakReference(sb);
            Console.WriteLine("before GC");
            Console.WriteLine(weak.Target);
            GC.Collect();
            Console.WriteLine("after GC");
            if (weak.Target == null)
            {
                Console.WriteLine("now it has been cleared...");
            }
            else
            {
                Console.WriteLine(weak.Target);
            }

output:

before GC
weak
after GC
now it has been cleared...

在 debug 模式下,GC.Collect 方法仍然会工作,但是它的行为可能会受到一些影响。

在 debug 模式下,编译器会添加额外的调试信息到代码中,这些信息可能会影响垃圾回收器的行为。例如,编译器可能会保留一些对象的引用,以便调试器可以访问它们,这可能会导致这些对象不会被垃圾回收器回收,直到调试器不再需要它们为止。因此,当调用 GC.Collect 方法时,由于存在调试信息的影响,可能会出现一些对象无法被立即回收的情况。

此外,在 debug 模式下,垃圾回收器的性能也可能会受到一定的影响,因为编译器会添加额外的代码和调试信息,导致程序变得更加复杂和庞大,从而使垃圾回收器需要更长的时间来扫描和回收对象。

因此,如果需要在 debug 模式下进行垃圾回收操作,应该仔细考虑其影响,并进行充分的测试,以确保程序的正确性和性能。同时,还可以考虑使用其他的调试工具和技术来诊断和解决问题,避免对程序的垃圾回收行为产生不必要的影响。

所以,以上代码在debug模式下,会有截然不同的结果:

before GC
weak
after GC
weak
posted @ 2023-03-11 10:50  JohnYang819  阅读(138)  评论(0编辑  收藏  举报