GC.Collect如何影响垃圾回收
根據(jù)垃圾回收的算法,對(duì)象在內(nèi)存中是按代的方式存放的,通常情況下,當(dāng)?shù)?代沾滿分配的空間的時(shí)候(比如是256k),GC就會(huì)啟動(dòng)去回收第0代對(duì)象,幸存的第0代對(duì)象會(huì)被放入第1代中去,第1代的對(duì)象要等到放滿了才會(huì)收集,因此,越是年輕的代越是被頻繁的收集,由于通常情況下GC只收集第0代對(duì)象,既保證了可回收較多的內(nèi)存,又忽略了老一代的對(duì)象,從而加快了垃圾回收的速度,提升了性能。
因此當(dāng)調(diào)用gc.collect的時(shí)候,相當(dāng)于強(qiáng)制的對(duì)所有代,不管年輕還是老的都執(zhí)行一次回收。由于垃圾回收器在回收的資源的時(shí)候,正在執(zhí)行托管代碼的線程都會(huì)被掛起,具體的細(xì)節(jié)相當(dāng)復(fù)雜,因?yàn)橛械木€程運(yùn)行在不安全的點(diǎn),CLR不能執(zhí)行垃圾回收,因此CLR會(huì)采用線程劫持技術(shù),即通過(guò)修改線程棧的方法,來(lái)做垃圾回收。這種復(fù)雜性使得性能降低。除非確定大量的舊對(duì)象死亡,才考慮調(diào)用這個(gè)方法。
所以,在一般情況下,盡量不要干預(yù)垃圾回收器工作,即盡量避免主動(dòng)調(diào)用GC.Collect。
由于垃圾回收是異步的,CLR有一個(gè)專用的線程負(fù)責(zé)垃圾回收,因此,即使調(diào)用GC.Collect,也并不是實(shí)時(shí)的調(diào)用了Finalize,因此要保證確實(shí)調(diào)用了析構(gòu)方法,可以使用語(yǔ)句GC.WaitForPendingFinalizers()。
下面是一段代碼,通過(guò)注釋掉
GC.Collect();
GC.WaitForPendingFinalizers();
語(yǔ)句,看出端倪。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; using System.Reflection; namespace ConsoleApplication1 {class Program{static void Main(string[] args){AA aa1 = new AA("1");AA aa2 = new AA("2");AA aa3 = new AA("3");aa1 = null;aa2 = null;//GC.Collect();//GC.WaitForPendingFinalizers();var tmp = aa3;}}public class AA{public string id = "";public AA(string s){id = s;Console.WriteLine("對(duì)象AA_" + s + "被創(chuàng)建了");}~AA(){Console.WriteLine(id + " 析構(gòu)函數(shù)被執(zhí)行了");}} }當(dāng)語(yǔ)句被注釋掉的時(shí)候,雖然aa1和aa2都設(shè)成了null,但是垃圾回收并不是馬上就把它們回收掉。對(duì)象可能都被放在第0代上,等進(jìn)程結(jié)束的時(shí)候,由垃圾回收器一起回收。所以輸出如下,順序是321
但是當(dāng)取消注釋后,由于強(qiáng)制垃圾回收時(shí),aa1對(duì)象和aa2對(duì)象都是null,因此就把它們回收掉了。順序就是213了。
注意,如果aa1和aa2不設(shè)成null,那么強(qiáng)制回收時(shí),并不認(rèn)為這2個(gè)對(duì)象可以回收。因此還是會(huì)等到進(jìn)程結(jié)束的時(shí)候才會(huì)回收。
總結(jié)
以上是生活随笔為你收集整理的GC.Collect如何影响垃圾回收的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C语言初学者代码中的常见错误与瑕疵(9)
- 下一篇: UDP组播