C#的GC机制(来自网摘复制,未整理)
第一个就是很多人用.Net写程序,会谈到托管这个概念。那么.Net所指的资源托管到底是什么意思,是相对于所有资源,还是只限于某一方面资源?很多人对此不是很了解,其实.Net所指的托管只是针对内存这一个方面,并不是对于所有的资源;因此对于Stream,数据库的连接,GDI+的相关对象,还有Com对象等等,这些资源并不是受到.Net管理而统称为非托管资源。而对于内存的释放和回收,系统提供了GC-Garbage Collector,而至于其他资源则需要手动进行释放。
那么第二个概念就是什么是垃圾,通过我以前的文章,会了解到.Net类型分为两大类,一个就是值类型,另一个就是引用类型。前者是分配在栈上,并不需要GC回收;后者是分配在堆上,因此它的内存释放和回收需要通过GC来完成。GC的全称为“Garbage Collector”,顾名思义就是垃圾回收器,那么只有被称为垃圾的对象才能被GC回收。也就是说,一个引用类型对象所占用的内存需要被GC回收,需要先成为垃圾。那么.Net如何判定一个引用类型对象是垃圾呢,.Net的判断很简单,只要判定此对象或者其包含的子对象没有任何引用是有效的,那么系统就认为它是垃圾。
明确了这两个基本概念,接下来说说GC的运作方式以及其的功能。内存的释放和回收需要伴随着程序的运行,因此系统为GC安排了独立的线程。那么GC的工作大致是,查询内存中对象是否成为垃圾,然后对垃圾进行释放和回收。那么对于GC对于内存回收采取了一定的优先算法进行轮循回收内存资源。其次,对于内存中的垃圾分为两种,一种是需要调用对象的析构函数,另一种是不需要调用的。GC对于前者的回收需要通过两步完成,第一步是调用对象的析构函数,第二步是回收内存,但是要注意这两步不是在GC一次轮循完成,即需要两次轮循;相对于后者,则只是回收内存而已。
如何去释放,应该把这些操作放到哪里比较好呢。.Net提供了三种方法,也是最常见的三种,大致如下:
<!--[if !supportLists]-->1. <!--[endif]-->析构函数;
<!--[if !supportLists]-->2. <!--[endif]-->继承IDisposable接口,实现Dispose方法;
<!--[if !supportLists]-->3. <!--[endif]-->提供Close方法。
经过前面的介绍,可以知道析构函数只能被GC来调用的,那么无法确定它什么时候被调用,因此用它作为资源的释放并不是很合理,因为资源释放不及时;但是为了防止资源泄漏,毕竟它会被GC调用,因此析构函数可以作为一个补救方法。而Close与Dispose这两种方法的区别在于,调用完了对象的Close方法后,此对象有可能被重新进行使用;而Dispose方法来说,此对象所占有的资源需要被标记为无用了,也就是此对象被销毁了,不能再被使用。例如,常见SqlConnection这个类,当调用完Close方法后,可以通过Open重新打开数据库连接,当彻底不用这个对象了就可以调用Dispose方法来标记此对象无用,等待GC回收。明白了这两种方法的意思后,大家在往自己的类中添加的接口时候,不要歪曲了这两者意思。
在C#中,资源分为托管资源和非托管资源两种。GC在回收无用对象资源时,可以自动回收托管资源(比如托管内存),但对于非托管资源(比如Socket、文件、数据库连接)必须在程序中显式释放。
托管资源的回收首先需要GC识别无用对象,然后回收其资源。一般无用对象是指通过当前的系统根对象和调用堆栈对象不可达的对象。对象有一个重要的特点导致无用对象判断的复杂性:对象间的相互引用!如果没有相互引用,就可以通过“引用计数”这种简单高效的方式实现无用对象的判断,并实现实时回收。正是由于相互引用的存在导致GC需要设计更为复杂的算法,这样带来的最大问题在于丧失了资源回收的实时性,而变成一种不确定的方式。
对于非托管资源的释放,C#提供了两种方式:
1.Finalizer:写法貌似C++的析构函数,本质上却相差甚远。Finalizer是对象被GC回收之前调用的终结器,初衷是在这里释放非托管资源,但由于GC运行时机的不确定性,通常会导致非托管资源释放不及时。另外,Finalizer可能还会有意想不到的副作用,比如:被回收的对象已经没有被其他可用对象所引用,但Finalizer内部却把它重新变成可用,这就破坏了GC垃圾收集过程的原子性,增大了GC开销。
2.Dispose Pattern:C#提供using关键字支持Dispose Pattern进行资源释放。这样能通过确定的方式释放非托管资源,而且using结构提供了异常安全性。所以,一般建议采用Dispose Pattern,并在Finalizer中辅以检查,如果忘记显式Dispose对象则在Finalizer中释放资源。
可以说,GC为程序带来安全方便的同时也付出了不小的代价:一则丧失了托管资源回收的实时性,这在实时系统和资源受限系统中是致命的;二则没有把C#托管资源和非托管资源的管理统一起来,造成概念割裂。C++的定位之一是底层开发能力,所以不难理解GC并没有成为C++的语言特性。虽然我们在C++0x和各种第三方库都能看到GC的身影,但GC对于C++来讲并不是那么重要,至多是一个有益的补充。C++足以傲视C,并和C# GC一较高下的是它的RAII。以上介绍C#托管资源和非托管资源
private void button1_Click(object sender, EventArgs e)
{
AA a = new AA();
AA b = new AA();
AA c = new AA();
AA d = new AA();
{
~AA()
{
MessageBox.Show("析构函数被执行了");
private void button1_Click(object sender, EventArgs e)
{
AA a = new AA();
AA b = new AA();
AA c = new AA();
AA d = new AA();
GC.Collect();
public class AA
{
FileStream fs = new FileStream("D://a.txt",FileMode.Open);
~AA()
{
MessageBox.Show("析构函数被执行了");
private void button1_Click(object sender, EventArgs e)
{
如果是这样一种情况,哪么第二次点击的时候就会报错,原因是一个文件只能创建一个连接。哪么一定要释放掉第一个资源,才可以进行第二次的连接。哪么首先我们想到用GC.Collect(),来强制释放闲置的资源,修改代码如下:
private void button1_Click(object sender, EventArgs e)
{
GC.Collect();
public class AA:IDisposable
{
FileStream fs = new FileStream("D://a.txt",FileMode.Open);
~AA()
{
MessageBox.Show("析构函数被执行了");
}
#region IDisposable 成员
public void Dispose()
{
fs.Dispose();
MessageBox.Show("dispose执行了");
}
#endregion
好了,我们看到了,继承IDisposable接口以后会有一个Dispose方法(当然了,你不想继承也可以,但是接口给我们提供一种规则,你不愿意遵守这个规则,就永远无法融入整个团队,你的代码只有你一个人能看懂),好了闲话不说,这样一来我们的button1_Click改为private void button1_Click(object sender, EventArgs e)
{
private void button1_Click(object sender, EventArgs e)
{
public void Dispose()
{
fs.Dispose();
MessageBox.Show("dispose执行了");
GC.SuppressFinalize(this);
}
C#技术漫谈之垃圾回收机制(GC)_知识库_博客园
http://kb.cnblogs.com/page/106720/
转载于:https://www.cnblogs.com/felixzh/p/4308359.html
C#的GC机制(来自网摘复制,未整理)相关推荐
- CSDN技术网摘使用指南
什么是网摘? 网摘又名网页书签,英文原名是Social Bookmark,直译是"社会化书签".世界上第一个网摘站点del.icio.us的创始人Joshua发明了网摘.通俗地说, ...
- 网摘精灵的超级使用方法
网摘精灵的超级使用方法 1保证你已经拥有了网摘精灵软件. http://www.wangjianran.com/wangzhaijingling/ 到这里下载 2http://d.baidu.com ...
- 最好的网站宣传方法:网摘精灵
最好的网站宣传方法:网摘精灵 网摘精灵 软件名称:网摘精灵 软件语言:简体中文 当前版本:1.0 适用平台:windows 9x/windows me/windows 2000/windows xp/ ...
- 网摘-java面试笔试题大汇总
1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有 关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象包括 两个方面,一是过程抽 ...
- 32位jdk最大内存_你了解Java 内存区域和GC机制吗?
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- 转载:Java 内存区域和GC机制
原文链接:http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html 目录 Java垃圾回收概况 Java内存区域 Java对象的访 ...
- JAVA之JVM GC 机制与性能优化
1 背景介绍 与C/C++相比,JAVA并不要求我们去人为编写代码进行内存回收和垃圾清理.JAVA提供了垃圾回收器(garbage collector)来自动检测对象的作用域),可自动把不再被使用的存 ...
- Java 内存区域和GC机制
2019独角兽企业重金招聘Python工程师标准>>> 目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 J ...
- Java系列笔记(3) - Java 内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java内存区域和GC机制
Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 ...
最新文章
- python - paramiko模块 修改logging提示为静默
- dmg文件转换iso ultraiso_mac去除dmg打开密码的方法
- php tsrmg,php garbage collect
- iOS打开沙盒html,iOS WKWebView加载本地/沙盒HTML及css、images
- 最暖数据: 除夕有6.88亿人用微信红包传递狗年祝福
- 一篇相当不错的function入门文章
- 【报告分享】智能时代的商业地产数字变革与发展报告.pdf(附下载链接)
- 用递归实现求一个迷宫是否有通路
- JVM监控及诊断工具GUI篇之Arthas(二):jvm相关指令
- iOS 自定义视频播放器
- error.flash download failed-Target DLL has been cancelled
- python如何收集数据库_python 整理web数据库
- 苹果史上8款最失败产品
- ECCV2020 超分辨论文(附论文链接)
- 荟研新材料 毕克BYK420 水性涂料和颜料浓缩浆用液态流变助剂 抗流挂剂
- JavaScript 各种验证(转自呆木头)
- 蓝桥杯国赛 勾股定理
- JS基础_Unicode编码表
- 自顶向下语法分析方法
- java 计算x的n次方
热门文章
- 有关Spring中Resource的继承关系(代码解读)
- 牛逼!9种不同的方法帮助你提高国内访问Github的速度到2MB/s以上...
- 千万别把有本事挣钱的人,当成臭奸商
- 一个强大的网络库RxEasyHttp
- 清除html中table标签显示的数据,遍历查看/新增/删除/获取html中table中的标签
- 常见报错_mysql常见报错之SELECT list is not in GROUP BY clause
- python3读取网页内容_python3获取一个网页特定内容
- csv文件的读写--示例
- python bs4 基本应用
- 查询今天、昨天、本周、上周、本月、上月数据