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 ...
随机推荐
- C++中的异常处理(三)
C++中的异常处理(三) 标签: c++C++异常处理 2012-11-24 23:00 1520人阅读 评论(0) 收藏 举报 分类: 编程常识(2) 版权声明:本文为博主原创文章,未经博主允许 ...
- C#表达式树的初步了解
在很早以前就听说过表达式树了,但并没有去了解它.虽然自己用过linq to sql和linq to entity,但也就用着就用着,并没有去深究c#代码怎么会生成sql代码而不是IL.废话不多说了,开 ...
- tyvj4221 货车漂移
背景 蒟蒻中学的蒟蒻遇到了一些小问题. 描述 蒟蒻考完noip也就要回家种田了,他老家的田地在s点,可是种子市场在e点,为了购买种子,中途要经过很多城市,这导致快递费非常的贵(因为快到双11了),于是 ...
- Json数据
<title>无标题文档</title>//使用 jquery 必须的先加载 <script src="jquery-2.1.1.min.js"> ...
- HDOJ 1102 生成树
Constructing Roads Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- users
NAME users - print the user names of users currently logged in to the current host SYNOPSIS users [O ...
- macbook air 安装win7双系统
转自: http://jingyan.baidu.com/article/6d704a13f99f1a28da51ca49.html 1)遇到“No bootable device-insert bo ...
- mysql中的unsigned
unsigned 既为非负数,用此类型可以增加数据长度! 例如如果 tinyint最大是127,那 tinyint unsigned 最大 就可以到 127 * ...
- First Position of Target
For a given sorted array (ascending order) and a target number, find the first index of this number ...
- ARM 处理器的几个相关术语
生产ARM的厂商很多,自然ARM处理器的名字就五花八门.但是,它们有些共同点,那就是:架构和核心. 架构这个概念太宽不太懂,一般不同的架构会有不同的指令集,在不同的架构下面还可以有多种核心.核心就是指 ...