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/
C#的GC机制(来自网摘复制,未整理)的更多相关文章
- sql中case when语句的使用-来自网摘文章
Case具有两种格式.简单Case函数和Case搜索函数. --简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END ...
- 扩展easyui.datagrid,添加数据loading遮罩效果代码 --来自网摘收集
//jquery.datagrid 扩展 (function (){ $.extend($.fn.datagrid.methods, { //显示遮罩 loading: function(jq){ r ...
- Java 内存区域和GC机制分析
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java 内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- Java系列笔记(3) - Java 内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- 【转】Java之 内存区域和GC机制
转自:Leo Chin 目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage ...
- Java 内存区域和GC机制--备用
Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 ...
- JAVA内存区域和GC机制
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- 【转载】Java系列笔记(3) - Java 内存区域和GC机制
Java系列笔记(3) - Java 内存区域和GC机制 转载:原文地址http://www.cnblogs.com/zhguang/p/3257367.html 目录 Java垃圾回收概况 Java ...
随机推荐
- Java Socket 网络编程心跳设计概念
Java Socket 网络编程心跳设计概念 1.一般是用来判断对方(设备,进程或其它网元)是否正常动行,一 般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于 ...
- Gradle用户指南(3)-构建Java项目
1.构建基本的Java项目 为了使用 Java 插件,添加下面代码到构建文件: build.gradle apply plugin: 'java' 这个就是 定义一个 Java 项目的全部.它会将 J ...
- 学习Linux下的IP地址地理位置信息显示工具nali
首先详细教程已经有前辈做了详细的安装和使用介绍,本人只是参照学习和记录下自己的实际操做. 本文参考档:http://www.cnblogs.com/mchina/archive/2012/12/24/ ...
- C# JavascriptSerializer与匿名对象打造Json的完美工具
一:背景 在web项目中经常需要生成json数据,返回给前端ajax. 无论是ashx,还是WebMethod,可以人工的用字符串去拼接,最终得到json数据. 有没有更好的方法呢?我个人推荐使用Ja ...
- Windbg对过滤驱动DriverEntry函数下断点技巧
方法1: 1> 先用DeviceTree.exe查看指定的过滤驱动的Load Address(加载地址) 2> 再用LordPE.EXE查看指定过滤驱动文件的入口点地址 3> 计算过 ...
- [Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合
对象属性无序性 js对象是一个无序属性集合. var obj={}; obj.a=10; obj.b=30; 属性a和属性b并没有谁前谁后之说.for...in循环,先输出哪个属性都有可能.获取和设置 ...
- linux查看python安装路径,版本号
一.想要查看ubuntu中安装的Python路径 方法一:whereis python 方法二:which python 二.想要查看ubuntu中安装的python版本号 python
- HTTP HSTS协议和 nginx
导读 Netcraft 公司最近公布了他们检测SSL/TLS网站的研究,并指出只有仅仅5%的用户正确执行了HTTP严格传输安全HSTS.本文介绍nginx如何配置HSTS. 什么是HSTS HTTPS ...
- MYSQL注入天书之HTTP头部介绍
Background-5 HTTP头部介绍 在利用抓包工具进行抓包的时候,我们能看到很多的项,下面详细讲解每一项. HTTP头部详解 1. Accept:告诉WEB服务器自己接受什么介质类型,*/* ...
- LNK2005 连接错误解决办法
nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@ ...