成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺析Dotnet的垃圾回收

開(kāi)發(fā) 前端
在早期C++的時(shí)候,內(nèi)存分配和釋放都是由我們手動(dòng)處理的,而在公共語(yǔ)言進(jìn)行時(shí)CLR中,多了一個(gè)垃圾收集器GC,來(lái)充當(dāng)自動(dòng)內(nèi)存管理器,完成同樣的工作。

[[384762]]

本文轉(zhuǎn)載自微信公眾號(hào)「老王Plus」,作者老王Plus。轉(zhuǎn)載本文請(qǐng)聯(lián)系老王Plus公眾號(hào)。

在說(shuō)垃圾回收之前,先說(shuō)說(shuō)兩個(gè)概念:

  • 托管代碼,是由CLR管理的代碼
  • 非托管代碼,是由操作系統(tǒng)直接執(zhí)行的代碼

在早期C++的時(shí)候,內(nèi)存分配和釋放都是由我們手動(dòng)處理的,而在公共語(yǔ)言進(jìn)行時(shí)CLR中,多了一個(gè)垃圾收集器GC,來(lái)充當(dāng)自動(dòng)內(nèi)存管理器,完成同樣的工作。從此,對(duì)于開(kāi)發(fā)人員來(lái)說(shuō),我們可以不需要用顯式的代碼來(lái)執(zhí)行內(nèi)存管理。這樣做的好處是明顯的:大量相關(guān)內(nèi)存的錯(cuò)誤被消除了,比方?jīng)]有釋放對(duì)象導(dǎo)致的內(nèi)存泄露,或試圖訪問(wèn)已經(jīng)釋放的對(duì)象的內(nèi)存,等等。

為了防止不提供原網(wǎng)址的轉(zhuǎn)載,特在這里加上原文鏈接:https://abc.com

一、回收和管理托管資源

上面說(shuō)了,垃圾回收GC在Dotnet中是一個(gè)自動(dòng)的內(nèi)存管理器,是一種機(jī)制,用來(lái)清理和回收堆內(nèi)存中未引用的部分。

通常CLR會(huì)在這些情況下啟動(dòng)垃圾回收:

  • 需要在堆上分配內(nèi)存給一個(gè)新對(duì)象,但沒(méi)有足夠的空閑內(nèi)存時(shí);
  • 對(duì)象被強(qiáng)制Dispose時(shí);
  • 托管堆上已分配對(duì)象的內(nèi)存超過(guò)了閥值(這個(gè)閥值會(huì)動(dòng)態(tài)調(diào)整);
  • 調(diào)用了GC.Collect方法

這些內(nèi)容都是基礎(chǔ),了解了非常好,面試時(shí)有話可說(shuō)。不了解也沒(méi)關(guān)系,不會(huì)影響做一個(gè)好的程序出來(lái)。

下面的內(nèi)容如果能記住,倒是對(duì)于程序開(kāi)發(fā)很有幫助。

在Dotnet的垃圾回收機(jī)制中,回收器會(huì)自行優(yōu)化并適用于多種方案。但是,我們?nèi)匀豢梢愿鶕?jù)運(yùn)行環(huán)境來(lái)設(shè)置垃圾回收的類(lèi)型。

Dotnet的CLR提供了下面兩種類(lèi)型的垃圾回收:

  • 工作站垃圾回收
  • 服務(wù)器垃圾回收

這兩種回收機(jī)制,有一定的區(qū)別。

工作站回收,主要是為客戶端應(yīng)用設(shè)計(jì)的,也是程序默認(rèn)的回收機(jī)制。垃圾回收的過(guò)程,跑在觸發(fā)垃圾回收的用戶線程上,并使用相同的優(yōu)先級(jí)。這種方式,優(yōu)點(diǎn)是不會(huì)被掛起或延遲,缺點(diǎn)是需要與其它線程競(jìng)爭(zhēng)CPU時(shí)間。當(dāng)運(yùn)行環(huán)境中只有一個(gè)CPU時(shí),系統(tǒng)會(huì)自動(dòng)采用工作站方式,不管你設(shè)置成什么。

服務(wù)器回收,針對(duì)的是高吞吐的服務(wù)器應(yīng)用,回收過(guò)程跑在專(zhuān)用的高優(yōu)先級(jí)線程上,而且默認(rèn)是多線程在跑,所以效率更高,缺點(diǎn)是占用的資源會(huì)更多,而且由于線程之間的干擾和上下文切換,會(huì)影響整體性能。

所以,選擇什么樣的回收機(jī)制,需要認(rèn)真分析。通常普通應(yīng)用,工作站回收就好。如果是服務(wù)器端的API服務(wù),需要選擇服務(wù)器回收。而如果是在服務(wù)端需要啟動(dòng)多個(gè)實(shí)例進(jìn)行處理,比方對(duì)總線的數(shù)據(jù)保存,那還是工作站回收好。

設(shè)置垃圾回收方式,在開(kāi)發(fā)時(shí),可以在xxx.csproj文件中加入:

  1. <PropertyGroup>  
  2.   <ServerGarbageCollection>true</ServerGarbageCollection>  
  3. </PropertyGroup> 

其中,設(shè)置true就是服務(wù)器模式,設(shè)置false就是工作站模式,當(dāng)然,去掉這一行,默認(rèn)也是工作站模式。

對(duì)于生產(chǎn)環(huán)境中已經(jīng)上線的應(yīng)用,也可以修改回收模式。找到程序目錄中的xxx.runtimeconfig.json文件,在里面加入:

  1. "configProperties": { 
  2.   "System.GC.Server"true 

這兩個(gè)配置的關(guān)系是:如果開(kāi)發(fā)時(shí)在.csproj中加入了ServerGarbageCollection,那在發(fā)布時(shí)會(huì)自動(dòng)在.runtimeconfig.json中加入System.GC.Server。

二、回收和管理非托管資源

上面說(shuō)到的回收機(jī)制,針對(duì)的是托管資源。

對(duì)于非托管資源,GC不會(huì)主動(dòng)進(jìn)行回收。回收非托管資源,只能手工編寫(xiě)代碼并顯式的釋放。

通常來(lái)說(shuō),程序中用到的操作系統(tǒng)的資源文件、網(wǎng)絡(luò)或數(shù)據(jù)庫(kù)連接等,都屬于非托管資源,需要手工清理。

有兩種方法可以清理非托管理資源:

  • 使用終結(jié)器Finalize,并由GC回收
  • 手動(dòng)處理Dispose

2.1 使用終結(jié)器Finalize

終結(jié)器Finalize是System.Object的一個(gè)虛方法,這個(gè)方法在GC回收對(duì)象的內(nèi)存之前由垃圾回帳調(diào)用。我們可以重寫(xiě)這個(gè)方法,來(lái)釋放非托管資源。

多說(shuō)兩句:似乎MS對(duì)這個(gè)部分有些猶豫,所以這兒規(guī)則一直處在兩可之間。C#在析構(gòu)函數(shù)的支持上并不嚴(yán)格。System.Object支持重寫(xiě)Object.Finalize方法,但它創(chuàng)建的類(lèi)卻不支持,重寫(xiě)會(huì)報(bào)錯(cuò),而只能通過(guò)改寫(xiě)析構(gòu)函數(shù)來(lái)實(shí)現(xiàn),并由編譯器將代碼包裝在try塊中的析構(gòu)函數(shù)或重寫(xiě)的Finalize中,并由finally調(diào)用Object.Finalize來(lái)實(shí)現(xiàn)。

使用終結(jié)器,缺點(diǎn)也是比較明顯的。GC檢測(cè)到一個(gè)對(duì)象需要回收時(shí),會(huì)在一段不確定的時(shí)間之后調(diào)用終結(jié)器。這個(gè)不確定很討厭,我們很難預(yù)料什么時(shí)候?qū)ο蟊粚?shí)際釋放。

Finalize雖然看著是手動(dòng)清除非托管資源,其實(shí)還是由垃圾回收器去做的。它的最大作用是確保非托管資源一定被釋放。

2.2 手動(dòng)處理Dispose

手動(dòng)處理最重要的理由,是在需要的時(shí)候立即釋放,而不是讓垃圾回收器進(jìn)行不確定延時(shí)后的釋放。

手動(dòng)釋放,主要的工作是提供一個(gè)IDisposable.Dispose的實(shí)現(xiàn),來(lái)實(shí)現(xiàn)非托管資源的確定性釋放。這樣,當(dāng)需要釋放時(shí),調(diào)用Dispose方法,就會(huì)立即釋放非托管資源。

手動(dòng)處理實(shí)現(xiàn)起來(lái)很簡(jiǎn)單。框架提供了一個(gè)接口System.IDisposable:

  1. public interface IDisposable   
  2. {   
  3.     void Dispose();   
  4. }   

他只包含一個(gè)方法Dispose。使用時(shí),需要實(shí)現(xiàn)這個(gè)方法,在使用完成后及時(shí)釋放非托管資源。

同時(shí),Dispose方法還提供了GC.SuppressFinalize方法,來(lái)告訴GC對(duì)象已經(jīng)被手動(dòng)處理,不再需要調(diào)用終結(jié)器。

  1. public void Dispose()   
  2. {   
  3.     GC.SuppressFinalize(this);   
  4. }  

這種方式下,對(duì)象的內(nèi)存可以做到提前回收。

在某些情況下,可能無(wú)法調(diào)用IDisposable.Dispose方法來(lái)釋放非托管資源,但場(chǎng)景下又確實(shí)需要確定性地釋放,這時(shí)候可能通過(guò)重寫(xiě)Object.Finalize來(lái)實(shí)現(xiàn):

  1. public class MyClass     
  2. {     
  3.    ~MyClass()     
  4.    { 
  5.       //TODO: 釋放未托管的資源 
  6.    }     
  7. }     

有點(diǎn)奇怪,是不是?

其實(shí),這就是上邊我說(shuō)MS猶豫的地方。如果你直接重寫(xiě)Object.Finalize,像下面這樣:

  1. public class MyClass     
  2. {     
  3.    protected override void Finalize()     
  4.    {     
  5.       //TODO: 釋放未托管的資源 
  6.    }     
  7. }   

編譯時(shí)會(huì)報(bào)錯(cuò)Do not override object.Finalize. Instead, provide a destructor.,而他正確的寫(xiě)法,就是析構(gòu)函數(shù)。

上面說(shuō)的內(nèi)容,做成一個(gè)套路模板,就會(huì)是這樣的:

  1. public class MyClass : IDisposable 
  2.     private bool disposedValue; 
  3.  
  4.     protected virtual void Dispose(bool disposing) 
  5.     { 
  6.         if (!disposedValue) 
  7.         { 
  8.             if (disposing) 
  9.             { 
  10.                 // TODO: 釋放托管狀態(tài)(托管對(duì)象) 
  11.             } 
  12.  
  13.             // TODO: 釋放未托管的資源(未托管的對(duì)象)并替代終結(jié)器 
  14.             // TODO: 將大型字段設(shè)置為 null 
  15.             disposedValue = true
  16.         } 
  17.     } 
  18.  
  19.     ~MyClass() 
  20.     { 
  21.         Dispose(disposing: false); 
  22.     } 
  23.  
  24.     public void Dispose() 
  25.     { 
  26.         Dispose(disposing: true); 
  27.         GC.SuppressFinalize(this); 
  28.     } 

如果你看到了這兒,建議把上面這個(gè)套路模板存下來(lái)。這算是最完整的一個(gè)版本,網(wǎng)上能找到的,大多是簡(jiǎn)化版。

其實(shí),我們經(jīng)常使用的很多類(lèi),都實(shí)現(xiàn)了IDisposable接口。比如說(shuō),凡是可以用using來(lái)進(jìn)行調(diào)用類(lèi),就都實(shí)現(xiàn)了IDisposable接口。另外有一些類(lèi),把Dispose改成了一個(gè)別的名字,比方IO里的Close方法,就是一個(gè)Dispose。

另外,如果對(duì)象實(shí)現(xiàn)了IDisposable接口,而我們直接new了這個(gè)對(duì)象,那在使用結(jié)束后,我們就需要Dispose這個(gè)對(duì)象。因?yàn)榧热辉O(shè)計(jì)者選擇了Dispose,那結(jié)束時(shí)調(diào)用Dispose就是正確的。

三、總結(jié)

最后做個(gè)簡(jiǎn)單的總結(jié)。

垃圾回收模式選擇:應(yīng)用程序可分配的資源少,或者能夠競(jìng)爭(zhēng)到的資源少,就使用工作站模式,反之就使用服務(wù)器模式。

在回收處理上,托管資源就扔給GC自動(dòng)處理,非托管資源需要手動(dòng)處理:

其中:

Finalize是標(biāo)記出非托管資源可被回收,然后由GC去執(zhí)行回收工作 

Dispose是直接調(diào)用,并即時(shí)回收。

 

責(zé)任編輯:武曉燕 來(lái)源: 老王Plus
相關(guān)推薦

2009-06-23 14:15:00

Java垃圾回收

2009-09-18 09:16:06

.NET垃圾回收

2022-03-21 11:33:11

JVM垃圾回收器垃圾回收算法

2021-01-04 10:08:07

垃圾回收Java虛擬機(jī)

2017-08-04 10:53:30

回收算法JVM垃圾回收器

2022-01-20 10:34:49

JVM垃圾回收算法

2020-07-09 08:26:42

Kubernetes容器開(kāi)發(fā)

2021-11-05 15:23:20

JVM回收算法

2022-06-22 09:54:45

JVM垃圾回收Java

2009-07-06 17:34:22

Java垃圾回收

2009-12-30 10:14:29

JVM垃圾回收

2009-06-25 17:48:24

Java垃圾回收

2023-12-19 21:52:51

Go垃圾回收開(kāi)發(fā)

2010-12-13 11:14:04

Java垃圾回收算法

2023-08-08 10:29:55

JVM優(yōu)化垃圾回收

2014-06-19 10:48:18

RubyPython

2009-12-25 16:15:31

JVM垃圾回收算法

2017-06-12 17:38:32

Python垃圾回收引用

2011-07-04 16:48:56

JAVA垃圾回收機(jī)制GC

2009-08-21 17:31:58

C#垃圾回收
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产一级免费在线观看 | 久久亚洲视频网 | 亚洲一区二区精品 | 日韩欧美网 | 国产成人精品一区二区三区在线观看 | 国产在线一区二区三区 | 国产一区二区在线视频 | 在线观看中文字幕 | 一区二区三区av | 一级全黄少妇性色生活免费看 | 久久99这里只有精品 | 黄色三级免费网站 | 久草热播 | 久久99这里只有精品 | 干干干操操操 | 日本精品一区二区三区在线观看视频 | 精品视频一二区 | 97精品久久| 伦理午夜电影免费观看 | 国产97碰免费视频 | 中文一区二区视频 | 国产精品久久久久久久久久久免费看 | www.yw193.com| 成人综合视频在线 | 国产伦一区二区三区 | 精品久久精品 | 中文在线亚洲 | 午夜久久久 | 中文字幕在线观 | 欧美日韩在线成人 | 欧产日产国产精品国产 | 色视频www在线播放国产人成 | 丁香五月网久久综合 | 国产精成人 | 久久国产欧美日韩精品 | 五月婷婷在线播放 | 91精品91久久久 | 国产香蕉视频在线播放 | 男女视频免费 | a级片播放 | 综合精品 |