日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】.net框架读书笔记---CLR内存管理\垃圾收集(四)

發布時間:2023/12/10 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】.net框架读书笔记---CLR内存管理\垃圾收集(四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

弱引用

  當一個根指向一個對象時,該對象不可能被垃圾收集器收集,在這種情況下,通常說存在一個該對象的強引用(strong reference)。垃圾收集器還支持弱引用(weak reference)的概念。弱引用允許垃圾收集器收集對象,同時也允許應用程序訪問該對象,結果取決于時間。

  如果對象的弱引用存在,那么在垃圾收集執行后,該對象的內存將被執行清理。另一方面,要訪問一個弱引用對象,應用程序必須獲取該對象的一個強引用。如果應用程序在對象被執行之前得到了它的強引用,那么垃圾收集器將不再對該對象執行垃圾收集,因為這時存在一個該對象的強引用。

  下面代碼展示了弱引用的使用

class?Program
{
static?void?Main(?string?[] args)
{
SomeWeakReferenceMethod();
SomeStrongtReferenceMethod();
}

static?void?SomeWeakReferenceMethod()
{
//?創建一個強引用對象
SomeClass o?=?new?SomeClass();

WeakReference wr?=?new?WeakReference(o);

o?=?null?;?//?移除對象的強引用

o?=?wr.Target?as?SomeClass;

if?(o?==?null?)
{
//?出現過垃圾回收,對象的內存已經被回收
Console.WriteLine(?"?已經被回收?"?);
}
else
{
//?未出現垃圾回收
Console.WriteLine(?"?沒有被回收?"?+?o.X.ToString());
}

}
static?void?SomeStrongtReferenceMethod()
{
//?創建一個強引用對象
SomeClass o?=?new?SomeClass();
o?=?null?;?//?移除對象的強引用
try
{
Console.WriteLine(o.X);
}
catch
{
Console.WriteLine(?"?error?"?);
}
}


}

public?class?SomeClass
{
private?int?x;

public?int?X
{
get
{
return?this?.x;
}
}

public?SomeClass()
{
x?=?5?;
}
}

個人感覺弱引用機制有點像緩存,將一些操作起來比較費時(比如便利系統的硬盤)的東西第一次獲取之后暫時放入緩存中,并且將其引用置為null來減少應用程序的壓力,但是放置在緩存中可以再次使用(減少讀取時的壓力),至于是否能夠再次使用成功要看垃圾收集器。如果執行過垃圾收集,弱引用的對象將會被回收掉當然就無法再次使用了。

  System.WeakReference有兩個公用構造器:

  • public WeakReference(object target);
  • ?public WeakReference(object target, bool trackResurrection);

  target表示要追蹤的對象(上例中為SomeClass), trackResurrection表示是否要追蹤對象的復蘇,換句話說就是對象在執行Finalize方法后,是否還要追蹤該對象(對象執行Finlize后對象復蘇了) 。

  將不追蹤對象復蘇的WeakReference稱為短弱引用(short weak reference),而將追蹤對象復蘇的稱為長弱引用(long weak reference)。如果一個對象沒有Finalize方法,長短弱引用是一樣的,最好不要使用長弱引用,因為長弱引用在一個對象被執行終止后允許該對象復蘇,將會導致對象的狀態不可預知。

  一旦創建了對象的弱引用,通常將該對象的強引用設置為null,為了再次使用該對象,需要將弱引用轉換為一個強引用,通過WeakReference的Target屬性來完成的。如果target為null,那么對象已經被執行了垃圾收集,否則將會得到該對象的強引用。這時對象將不會被垃圾收集器收集了。

弱引用的內部機理

  需要再次探究托管堆。托管堆中包含了兩個內部數據結構來管理弱引用。即短弱引用表和長弱引用表。這兩個表包含著一些指針,他們引用著托管堆對象。

  當創建一個WeakReference對象時,它會在兩個弱引用表中選擇一個(長短弱引用相應對應),并在其中尋找一個空白插槽。該插槽的值將被設為我們希望追蹤對象的地址---也就是new WeakReference構造的那個對象的地址,弱引用表將不會認為是應用程序的根,否則垃圾收集器將不能收集它們中的指針引用的對象。

  垃圾收集器運行時發生的一系列事情:

  • 垃圾收集器構造一個可達對象的圖(.net框架讀書筆記---CLR內存管理\垃圾收集(一));
  • 垃圾收集器掃描短弱引用表,如果表中的對象不是前面可達對象圖的一部分(對象已經不是根,在上面的例子中o已經被置為null了),那么表示該對象是一個不可達的對象,將短弱引用表中對應插槽的值將被設置為null(Target為null了);
  • 垃圾收集器掃描終止化鏈表(.net框架讀書筆記---CLR內存管理\垃圾收集(二))。如果該鏈表中指針引用的對象不是可達對象圖的一部分,那么該對象將是不可達對象,它將被從終止化鏈表轉移到終止化可達隊列上。這時對象由成為可達對象圖的一部分了。
  • 垃圾收集器掃描長弱引用表,如果表中的對象不是前面可達對象圖的一部分(該圖現在已經包括終止化可達隊列中引用的對象了),那么表示該對象是一個不可達的對象,將長弱引用表中對應插槽的值將被設置為null(Target為null了);
  • 垃圾收集器壓縮內存,填充不可達對象空出的位置。

  繼續分析代碼

if?(o?==?null?)
{
//?出現過垃圾回收,對象的內存已經被回收
Console.WriteLine(?"?已經被回收?"?);
}
else
{
//?未出現垃圾回收
Console.WriteLine(?"?沒有被回收?"?+?o.X.ToString());
}

因為在此之前o已經被置為null了,所以它已經是一個不可達對象,如果執行垃圾收集器,o自然不在可達對象圖中,那么垃圾收集器將會將短弱引用表中插槽對應的值設為null,這樣Target將返回null,上面代碼自然會執行if里面的代碼。如果垃圾收集器還沒有執行,雖然o已經為null,但是短弱引用插槽依然保存著對象的引用,那么Target將會返回對象的引用,使對象繼續可達,可以使用,當然上面代碼就會執行else里面的代碼。

  短弱引用并不追蹤對象的復蘇。只要垃圾收集器判斷對象成為不可達的對象,它就會把短弱引用表中對應的指針設置為null。如果對象重寫了Finalize方法,那么這時該方法還沒有被調用,所以對象仍然存在。此時target仍然返回null,雖然這時對象已經進入終止化可達隊列,對象仍然存在。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的【转】.net框架读书笔记---CLR内存管理\垃圾收集(四)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。