19

基本的な違いは、弱い参照は GC の実行ごとに要求される (メモリ フットプリントを低く保つ) ことになっているのに対し、ソフト参照は GC が実際にメモリを必要とするまでメモリに保持する必要がある (寿命を延ばそうとしますが、いつでも失敗する可能性があります。これは、特にかなり高価なオブジェクトのキャッシュなどに役立ちます)。

私の知る限り、弱い参照が .NET のオブジェクトの有効期間にどのように影響するかについて明確な声明はありません。それらが真の弱い参照である場合、それらはまったく影響を与えるべきではありませんが、それはまた、キャッシュの主な目的のためにそれらをかなり役に立たなくするでしょう(私は間違っていますか?)。一方、それらがソフト リファレンスのように振る舞う場合、その名前は少し誤解を招きます。

個人的には、ソフト参照のように振る舞うと想像していますが、それは単なる印象であり、根拠はありません。

もちろん、実装の詳細が適用されます。.NET の弱参照に関連する考え方について質問しています。それらは寿命を延ばすことができますか、それとも真の弱参照のように動作しますか?

(多くの関連する質問にもかかわらず、この特定の問題に対する答えはまだ見つかりませんでした。)

4

3 に答える 3

14

C#の弱参照は実際にはソフトですか?

いいえ。

私はそこに間違っていますか?

あなたはそこで間違っています。弱参照の目的は、あなたが意味する意味でのキャッシュではありません。それはよくある誤解です。

それらは寿命を延ばすことができますか、それとも真の弱い参照のように動作しますか?

いいえ、寿命は延びません。

次のプログラム(F#コード)について考えてみます。

do
  let x = System.WeakReference(Array.create 0 0)
  for i=1 to 10000000 do
    ignore(Array.create 0 0)
  if x.IsAlive then "alive" else "dead"
  |> printfn "Weak reference is %s"

このヒープは、ガベージコレクションの対象となる空の配列を割り当てます。次に、10M回ループして、到達不能な配列を割り当てます。これはメモリの負荷をまったく増加させないため、弱参照によって参照される配列を収集する動機がないことに注意してください。それにもかかわらず、プログラムは「弱い参照は死んでいます」と出力します。それにもかかわらず、それは収集されたからです。これは弱参照の動作です。ソフト参照は、そのメモリが実際に必要になるまで保持されていました。

別のテストプログラム(F#コード)は次のとおりです。

open System

let isAlive (x: WeakReference) = x.IsAlive

do
  let mutable xs = []
  while true do
    xs <- WeakReference(Array.create 0 0)::List.filter isAlive xs
    printfn "%d" xs.Length

これにより、デッドウィーク参照が除外され、リンクリストの先頭に新しい参照が追加され、リストの長さが毎回出力されます。私のマシンでは、これは1,000を超えることはありません。おそらく、すべての弱参照がgen0コレクションごとに収集されるため、サイクルが増加してからゼロに低下します。繰り返しますが、これは弱参照の動作であり、ソフト参照ではありません。

この動作(gen0コレクションでの弱参照オブジェクトの積極的なコレクション)が、弱参照をキャッシュに不適切な選択にしていることに注意してください。キャッシュで弱参照を使用しようとすると、理由もなくキャッシュが大量にフラッシュされることに気付くでしょう。

于 2013-01-06T20:41:01.937 に答える
9

それらが指すオブジェクトの寿命を延ばすことを示す情報は見たことがありません。また、GCが到達可能性を判断するために使用するアルゴリズムについて読んだ記事でも、このように言及されていません。したがって、オブジェクトの寿命には影響しないと思います。

弱い
このハンドルタイプは、オブジェクトを追跡するために使用されますが、オブジェクトを収集できるようにします。オブジェクトが収集されると、GCHandleの内容はゼロになります。弱参照はファイナライザーが実行される前にゼロ化されるため、ファイナライザーがオブジェクトを復活させたとしても、弱参照はゼロ化されたままです。

WeakTrackResurrection
このハンドルタイプはWeakに似ていますが、ファイナライズ中にオブジェクトが復活した場合、ハンドルはゼロになりません。

http://msdn.microsoft.com/en-us/library/83y4ak54.aspx


到達不能なオブジェクトがガベージコレクションを生き残ることができるメカニズムがいくつかあります。

  • オブジェクトの生成は、発生したGCの生成よりも大きくなります。これは、ラージオブジェクトヒープに割り当てられ、この目的では常にGen2と見なされるラージオブジェクトにとって特に興味深いものです。
  • ファイナライザーを備えたオブジェクトと、それらから到達可能なすべてのオブジェクトは、GCを生き残ります。
  • 古いオブジェクトからの以前の参照が若いオブジェクトを存続させることができるメカニズムがあるかもしれませんが、それについてはよくわかりません。
于 2011-10-13T15:03:27.213 に答える
-1

はい
弱参照はオブジェクトの寿命を延ばさないため、すべての強参照が範囲外になるとガベージ コレクションが可能になります。これらは、初期化にコストがかかる大きなオブジェクトを保持するのに役立ちますが、アクティブに使用されていない場合はガベージ コレクションに使用できるはずです。

于 2011-10-13T14:49:35.490 に答える