如:
class BigData
{
}
class Program
{
static BigData cache;
public static BigData DataCache
{
get
{
if (cache== null) cache= new BigData();
return cache;
}
}
}
但是这样做在某些时候会存在一些弊端,如:
1. 当dataCache并没有被频繁使用,甚至因为某些原因仅仅被使用了一次时会造成内存资源的浪费。
2. 由于GC只能回收不可达对象,因此即便内存不足,GC也无法回收这些闲置资源。
这时建议你使用 WeakReference 来重构你的程序,以便获得更好的系统性能。
WeakReference :“弱引用”,即在引用对象的同时仍然允许对该对象进行垃圾回收。
使用弱引用后,不应该再使用强引用,有关细节可以参考SDK帮助文档。
class BigData
{
~BigData()
{
Console.WriteLine("Destory...");
}
public void Test()
{
Console.WriteLine("Test");
}
}
class Program
{
static WeakReference cache = new WeakReference(null);
public static BigData DataCache
{
get
{
BigData data = cache.Target as BigData;
if (data == null)
{
data = new BigData();
cache.Target = data;
}
return data;
}
}
static void Main(string[] args)
{
DataCache.Test();
DataCache.Test();
GC.Collect();
DataCache.Test();
}
}
改进后的程序,我们依旧可以实现我们缓存的目的,而GC也可以在合时的时候释放cache占用的内存。
.NET中的缓存功能多采用了类似的设计。
当然并非要求所有的场合都适合使用弱引用。
补充:
弱引用分为"短弱引用(Short Week Reference)"和"长弱引用(Long Week Reference)",其区别是长弱引用在对象的Finalize方法被GC调用后依然追踪对象。基于安全考虑,不推荐使用长弱引用。
因此建议使用
WeakReference wr = new WeakReference(object);或
WeakReference wr = new WeakReference(object, false);
来自:http://www.rainsts.net/feed.asp?q=comment&id=78
======================================
[1]强引用 如果有强引用存在,GC是不会回收对象的。 [2]弱引用 弱引用可以让您保持对对象的引用, 同时允许GC在必要时释放对象,回收内存。 [3]弱引用使用场景 对于那些创建便宜但耗费大量内存的对象, 希望保持该对象,又要在应用程序需要时使用, 同时希望GC必要时回收时,可以考虑使用弱引用。
在了解使用WeakReference之前.我想大家先了解一下CLR无用内存回收机制. 1.NET中的托管对象. 1>普通对象:即没有使用系统资源的对象,故没胡析构函数. 2>使用系统资源的对象:带析构函数并在其中释放系统资源.(文件,各种流,网络连接,数据库连接等(内存也是系统资源,但这里的系统资源并不包括内存)). 2.使用系统资源的五大步骤: 1>为代表资源的类型分配内存. 2>初始化资源的状态.请求非内存的系统资源(打开文件,建立数据库连接等) 3>通过访问类型的实例及其成员来访问资源。 4>清空资源状态,释放系统资源。(关闭文件,关闭数据库连接等)。 5>释放内存。 对于普通对象,只有上面的.1,3,5步,而对于使用了系统资源的对象才有上面的全部5步。 CLR默认调用Finalize()来实现第4>步。使用了系统资源的类应该实现Dispose()方法,通过程序员主动调用来释放使用的系统资源,避免CLR调用Finalize()方法带来的性能损失。因为无用内存回收(Garbage Collection 简称GC)运行时,会中止当前程序的执行,大大影响程序的性能。 3.引用类型对象在内存中的分配 Class Test{ private int x,y; public Test(int x,int y){ this.x = x; this.y = y; } } Test t1 = new Test(0,0); Test t2 = new Test(1,1); Test t3 = new Test(2,4); 当new Test(0,0)所执行的动作如下: 1>托管堆manage heap 中分配指定类型所需字节空间作为存储其对象内存空间并将该空间清0; 2>初始化对象的2个附加成员:指向类型方法表的指针和syncBlockIndex指针。 3>引起对构造函数的调用。 4>返回指向新建对象的引用。(把一个对象引用分配给一个变量,该变量就包含对对象的一个强引用。GC不会收回强引用任在使用的对象。只有当变量离开作用域时,或是显式的给变量分配VB.NET(Nothing) or C#.NET (NULL)时,强引用才被删除。) ---Stack------ ----------------Manage Heap--------------------- t3 objact t3 t2 objact t2 t1 objact t1 4.CLR GC内存分配 当对象过多,manage heap分配光了或者不足分配新的对象时,CLR启动 GC,这时主线程被停止运行。GC将堆中不再被使用的对象占用的内存释放掉,然后整理堆,使剩余空间连续。如果没有可以释放的对象,或者释放了无用对象后内存还是不足,则CLR会抛出一个OutOfMemoryException异常。 5.GC如何判断对象不再使用 每一个应用都有一组根,这些根包括了标示托管堆中一组对象的存储单元。被认为是根的对象包括: 1.所有的全局和静态对象; 2.一个线成栈中的局部对象和函数的参数; 3.任何CPU寄存器包含的指针指向的对象; 上面根的列表由JIT和CLR维护并且GC可以访问。 开始无用单元回收后GC就开始遍历根,找到第一个根指向的对象,沿着这个对象向下找,找到这个对象所有引用的对象,以及引用之引用,并将其放入到一个集合中。这一个完成后,就接着找下一个根。一旦GC 发现某个对象已经在集合中,就停止这个分支的搜寻以防止重复和引用死循环。 完成后,GC就有了一个所有根可以访问到的对象的集合,这个集合中没有的对象就认为是无用的。如下:
来自:http://hi.baidu.com/czh0221/blog/item/57368f827716d9b76d81195b.html
浅谈弱引用在程序设计中的应用与内存优化
本文探讨了在程序设计中使用弱引用替代全局缓存设计的方法,以减少内存资源的浪费并提升系统性能。通过实例展示了如何使用弱引用实现缓存目的,同时让GC在适当的时候释放资源。文章还详细解释了CLR无用内存回收机制,包括引用类型对象在内存中的分配、GC如何判断对象不再使用以及Finalize方法的作用。最后介绍了WeakReference的使用场景和注意事项。
378

被折叠的 条评论
为什么被折叠?



