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

发布于 2024-12-09 19:30:57 字数 401 浏览 0 评论 0原文

基本区别在于,弱引用应该在每次 GC 运行时声明(保持低内存占用),而软引用应该保留在内存中,直到 GC 实际需要内存为止(它们试图延长生命周期,但可能随时失败,这对于例如缓存(尤其是相当昂贵的对象的缓存)很有用。

据我所知,关于弱引用如何影响 .NET 中对象的生命周期,还没有明确的说明。如果它们是真正的弱引用,它们根本不应该影响它,但这也会使它们对于我认为缓存的主要目的来说毫无用处(我错了吗?)。另一方面,如果他们表现得像软裁判,他们的名字就会有点误导。

就我个人而言,我认为它们的行为就像软引用,但这只是一种印象,并没有根据。

当然,实施细节也适用。我问的是与 .NET 弱引用相关的心态 - 它们是否能够延长生命周期,或者它们的行为是否像真正的弱引用?

(尽管有很多相关问题,但我还找不到这个具体问题的答案。)

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 e.g. caches especially of rather expensive objects).

To my knowledge, there is no clear statement as to how weak references influence the lifetime of an object in .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?

(Despite a number of related questions I could not find an answer to this specific issue yet.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

猫烠⑼条掵仅有一顆心 2024-12-16 19:30:57

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 收集中都会收集所有弱引用。再次强调,这是弱引用而不是软引用的行为。

请注意,这种行为(在第 0 代集合中积极收集弱引用对象)正是使弱引用成为缓存的糟糕选择的原因。如果您尝试在缓存中使用弱引用,那么您会发现缓存无缘无故地被大量刷新。

Are C# weak references in fact soft?

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):

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. 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):

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. It ramps up and then falls to zero in cycles, presumably because all of the weak references are collected at every gen0 collection. 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. If you try to use weak references in your cache then you'll find your cache getting flushed a lot for no reason.

以歌曲疗慰 2024-12-16 19:30:57

我没有看到任何信息表明它们会增加它们指向的对象的生命周期。我读到的有关 GC 用于确定可达性的算法的文章也没有以这种方式提及它们。所以我希望它们对对象的生命周期没有影响。


此句柄类型用于跟踪对象,但允许收集该对象。当对象被收集时,GCHandle 的内容被清零。弱引用在终结器运行之前被清零,因此即使终结器复活了对象,弱引用仍然被清零。

WeakTrackResurrection
此句柄类型与 Weak 类似,但如果对象在终结期间复活,句柄不会归零。

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


这里是一些无法访问的对象可以在垃圾回收中幸存下来的机制。

  • 对象的代数大于发生的 GC 的代数。这对于大对象来说特别有趣,因为它们分配在大对象堆上,并且为此目的始终被视为 Gen2。
  • 具有终结器的对象以及可从它们访问的所有对象在 GC 中仍然存在。
  • 可能存在一种机制,旧对象的先前引用可以使年轻对象保持活动状态,但我对此不确定。

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. 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. Weak references are zeroed before the finalizer runs, so even if the finalizer resurrects the object, the Weak reference is still zeroed.

WeakTrackResurrection
This handle type is similar to Weak, but the handle is not zeroed if the object is resurrected during finalization.

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. This is particularly interesting for large objects, which are allocated on the large-object-heap and are always considered Gen2 for this purpose.
  • Objects with a finalizer and all objects reachable from them survive the GC.
  • There might be a mechanism where former references from old objects can keep young objects alive, but I'm not sure about that.
趁微风不噪 2024-12-16 19:30:57


弱引用不会延长对象的生命周期,因此一旦所有强引用超出范围,就可以对其进行垃圾回收。它们对于保存初始化成本昂贵的大型对象很有用,但如果它们没有被积极使用,则应该可用于垃圾收集。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文