一,什麼是GC緩存
1,GC是垃圾回收器,通常來講系統會自動檢測不會使用的對象或變量進行內存的釋放,不須要手動調用,用Collect()就是強制進行垃圾回收,使內存獲得及時的釋放,讓程序效率更高.函數
2,GC:只負責回收託管對象,不負責回收非託管對象。this
那什麼是垃圾? 垃圾是徹底訪問不到的東西了,就是當前程序執行後該對象或值沒有被引用spa
以下圖:線程
代碼以下:code
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TestDemo { public class TestDemo { private static Test t = new Test()//靜態的不可能被回收 靜態持有的引用也不會被回收 { Id = 123, Name = "Test" }; public static void show() { ///{}這個括號是代碼分塊的意思,兩個塊之間是不影響的,第一塊執行完後,通常來講就是會被主動GC釋放 ///而這裏obj沒有被釋放的緣由是由於靜態遍歷對obj這個引用類型變量的使用 { object obj= new { Name = 1 }; t.obj = obj; int i = 3;//都會被GC TestDemo testDemo = new TestDemo();//都會被GC } { GC.Collect();//主動GC } } } public class Test { public int Id { get; set; } public string Name { get; set; } public object obj { get; set; } } }
總結:程序執行完會回收垃圾,這個obj還在靜態的t使用,因此沒有被釋放對象
那GC怎麼回收呢?
1,new的時候發現內存不夠 就去遍歷全部堆的對象,標記訪問不到,而後啓動一個線程來清理內存
2,清除標記了的對象,其餘挪動,而後整齊擺放,因此這個時候所有線程中止,不容許操做內存
3,內存不夠的是指一級對象的內存,有個臨界值,也不是所有的堆的大小blog
GC回收執行的過程:
1, 首次GC前 所有對象都是0級
2, 第一次GC後,還保留的對象叫1級
3, 回收先找0級對象,若是空間還不夠,再去找1級對象,這以後,還存在的對象就變成2級
4, 0級不夠,1級也不夠,2級還不夠,那就內存溢出了
5,越是最近分配的,越是會被回收 好比for循環建立對象內存
大對象和正常的對象緩存的地址是不同的。
大對象策略:若是大於某個值的對象85k,單獨管理,用的是鏈表(碎片),避免頻繁的內存移動資源
二,析構函數和IDisposable的區別?
~Class() 析構函數: 主要是用來釋放非託管資源,等着GC的時候去把非託管資源釋放掉 系統自動執行
GC回收的時候,CLR必定調用的,可是可能有延遲(釋放對象不知道要多久呢)
Dispose() :也是釋放非託管資源的,主動釋放,方法自己是沒有意義的,咱們須要在方法裏面實現對資源的釋放
GC不會調用,而是用對象時,使用者主動調用這個方法,去釋放非託管資源,
而不是說對象釋放的時候,會去自動調用Dispose方法,而後在用完對象時,咱們主動去執行dispose方法,固然能夠是using的快捷方式
以下代碼:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TestDemo { public class TestDemoThree { public static void show() { { for (int i = 0; i < 2; i++) { TestThree @class = new TestThree() { Id = i, Name = "TestThree" }; } } { GC.Collect(); //主動GC的時候,CLR必定調用的析構函數 } { ///using 這個會去調用調用的dispose,至關於try後的finally using (TestThree TestThree = new TestThree() { Id = 1, Name = "444" }) try { //using至關於 } finally { //調用的dispose() } } } public class TestThree : IDisposable { public int Id { get; set; } public string Name { get; set; } ~TestThree() { Console.WriteLine($"執行{this.GetType().Name}~TestThreeDispose"); } public void Dispose() { Console.WriteLine($"執行{this.GetType().Name}Dispose"); } } } }
主動執行GC執行結果
using執行結果