C#GC垃圾回收和析構函數和IDisposable的使用

一,什麼是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執行結果

相關文章
相關標籤/搜索