简体   繁体   English

C#弱引用实际上是软的吗?

[英]Are C# weak references in fact soft?

The basic difference is that weak references are supposed to be claimed on each run of the GC (keep memory footprint low) while soft references ought to be kept in memory until the GC actually requires memory (they try to expand lifetime but may fail anytime, which is useful for eg caches especially of rather expensive objects). 基本的区别在于,应该在GC的每次运行中声明弱引用(保持内存占用率低),而软引用应该保留在内存中,直到GC实际需要内存(它们尝试扩展生命周期但可能随时失败,这对于例如特别是相当昂贵的对象的高速缓存是有用的。

To my knowledge, there is no clear statement as to how weak references influence the lifetime of an object in .NET. 据我所知,没有明确的陈述说明弱引用如何影响.NET中对象的生命周期。 If they are true weak refs they should not influence it at all, but that would also render them pretty useless for their, I believe, main purpose of caching (am I wrong there?). 如果它们是真正的弱参考,它们根本不应该影响它,但是这也会使它们对于我们认为缓存的主要目的而言毫无用处(我错了吗?)。 On the other hand, if they act like soft refs, their name is a little misleading. 另一方面,如果他们的行为像软参考,他们的名字有点误导。

Personally, I imagine them to behave like soft references, but that is just an impression and not founded. 就个人而言,我想他们的行为就像软参考,但这只是一种印象,而不是创立。

Implementation details apply, of course. 当然,实施细节也适用。 I'm asking about the mentality associated with .NET's weak references - are they able to expand lifetime, or do they behave like true weak refs? 我问的是与.NET的弱引用相关的心态 - 它们是否能够延长寿命,还是它们的行为像真正的弱引用?

(Despite a number of related questions I could not find an answer to this specific issue yet.) (尽管有一些相关的问题我还没找到这个具体问题的答案。)

Are C# weak references in fact soft? C#弱引用实际上是软的吗?

No. 没有。

am I wrong there? 我错了吗?

You are wrong there. 你错了。 The purpose of weak references is absolutely not caching in the sense that you mean. 弱引用的目的绝不是你所指的意义上的缓存。 That is a common misconception. 这是一种常见的误解。

are they able to expand lifetime, or do they behave like true weak refs? 他们是否能够延长寿命,或者他们是否表现得像真正的弱点?

No, they do not expand lifetime. 不,他们不会延长寿命。

Consider the following program (F# code): 考虑以下程序(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"

This heap allocates an empty array that is immediately eligible for garbage collection. 此堆分配一个空数组,该数组立即符合垃圾回收的条件。 Then we loop 10M times allocating more unreachable arrays. 然后我们循环10M次分配更多无法访问的数组。 Note that this does not increase memory pressure at all so there is no motivation to collect the array referred to by the weak reference. 请注意,这根本不会增加内存压力,因此没有动机收集弱引用所引用的数组。 Yet the program prints "Weak reference is dead" because it was collected nevertheless. 然而,程序打印出“弱引用已死”,因为它仍然被收集。 This is the behaviour of a weak reference. 这是弱引用的行为。 A soft reference would have been retained until its memory was actually needed. 软件引用将被保留,直到实际需要其内存为止。

Here is another test program (F# code): 这是另一个测试程序(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

This keeps filtering out dead weak references and prepending a fresh one onto the front of a linked list, printing out the length of the list each time. 这样可以过滤掉无效的弱引用,并将新的引用添加到链表的前面,每次打印出列表的长度。 On my machine, this never exceeds 1,000 surviving weak references. 在我的机器上,这永远不会超过1,000个幸存的弱引用。 It ramps up and then falls to zero in cycles, presumably because all of the weak references are collected at every gen0 collection. 它会逐渐上升然后在周期内降至零,大概是因为所有的弱引用都是在每个gen0集合中收集的。 Again, this is the behaviour of a weak reference and not a soft reference. 同样,这是弱引用的行为,而不是软引用。

Note that this behaviour (aggressive collection of weakly referenced objects at gen0 collections) is precisely what makes weak references a bad choice for caches. 请注意,这种行为(gen0集合中弱引用对象的积极集合)正是使弱引用成为缓存的错误选择的原因。 If you try to use weak references in your cache then you'll find your cache getting flushed a lot for no reason. 如果您尝试在缓存中使用弱引用,那么您将发现您的缓存无缘无故地被刷新了很多。

I have seen no information that indicates that they would increase the lifetime of the object they point to. 我没有看到任何信息表明它们会增加它们指向的对象的生命周期。 And the articles I read about the algorithm the GC uses to determine reachability do not mention them in this way either. 我读到的关于GC用来确定可达性的算法的文章也没有以这种方式提及它们。 So I expect them to have no influence on the lifetime of the object. 所以我希望它们对对象的生命周期没有影响。

Weak
This handle type is used to track an object, but allow it to be collected. 此句柄类型用于跟踪对象,但允许收集它。 When an object is collected, the contents of the GCHandle are zeroed. 收集对象时,GCHandle的内容将归零。 Weak references are zeroed before the finalizer runs, so even if the finalizer resurrects the object, the Weak reference is still zeroed. 在终结器运行之前,弱引用被归零,因此即使终结器恢复对象,弱引用仍然归零。

WeakTrackResurrection WeakTrackResurrection
This handle type is similar to Weak, but the handle is not zeroed if the object is resurrected during finalization. 此句柄类型类似于Weak,但如果在完成期间对象复活,则句柄不会归零。

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


There are a few mechanism by which an object that's unreachable can survive a garbage collection. 有一些机制可以使一个无法访问的对象在垃圾收集中存活下来。

  • The generation of the object is larger than the generation of the GC that happened. 对象的生成大于发生的GC的生成。 This is particularly interesting for large objects, which are allocated on the large-object-heap and are always considered Gen2 for this purpose. 这对于大对象特别有意义,大对象在大对象堆上分配,并且为此目的始终被视为Gen2。
  • Objects with a finalizer and all objects reachable from them survive the GC. 具有终结器的对象和从它们可以到达的所有对象在GC中存活。
  • There might be a mechanism where former references from old objects can keep young objects alive, but I'm not sure about that. 可能有一种机制,旧的对象的前引用可以保持年轻的对象存活,但我不确定。

Yes
Weak references do not extend the lifespan of an object, thus allowing it to be garbage collected once all strong references have gone out of scope. 弱引用不会延长对象的生命周期,因此一旦所有强引用都超出范围,就允许对其进行垃圾回收。 They can be useful for holding on to large objects that are expensive to initialize but should be avaialble for garabage collection if they are not actively in use. 它们可用于保留初始化成本昂贵的大型对象,但如果不积极使用,则应该可用于收集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM