基本的不同之处在于,应该在每次运行GC时声明弱引用(保持内存占用率低),而软引用应该保留在内存中,直到GC实际需要内存(它们尝试扩展生命周期但可能随时失败,这对于例如特别是相当昂贵的对象的缓存很有用)。
据我所知,没有明确说明弱引用如何影响.NET中对象的生命周期。如果它们是真正的弱参考,它们根本不应该影响它,但是这也会使它们对于我们认为缓存的主要目的而言毫无用处(我错了吗?)。另一方面,如果他们的行为像软参考,他们的名字有点误导。
就我个人而言,我认为它们的行为类似于软参考,但这只是一种印象,而不是创立。
当然,实施细节也适用。我问的是与.NET的弱引用相关的心态 - 它们是否能够延长寿命,还是它们的行为像真正的弱引用?
(尽管有许多相关问题我还没找到这个具体问题的答案。)
答案 0 :(得分:13)
C#弱引用实际上是否软?
没有
我在那里错了吗?
你错了。弱引用的目的绝对是 not 缓存,就像你的意思。这是一种常见的误解。
他们能够延长寿命,还是表现得像真正的弱参考?
不,他们不会延长寿命。
考虑以下程序(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集合中积极收集弱引用的对象)正是弱引用对于缓存的错误选择。如果您尝试在缓存中使用弱引用,那么您将发现您的缓存无缘无故地被刷新了。
答案 1 :(得分:8)
我没有看到任何信息表明他们会增加他们指向的对象的生命周期。我读到的关于GC用来确定可达性的算法的文章也没有以这种方式提及它们。所以我希望它们对对象的生命周期没有影响。
弱
此句柄类型用于跟踪对象,但允许收集它。收集对象时,GCHandle的内容将归零。在终结器运行之前,弱引用被归零,因此即使终结器恢复对象,弱引用仍然归零。WeakTrackResurrection
此句柄类型与Weak类似,但如果在完成期间对象复活,则句柄不会归零。
http://msdn.microsoft.com/en-us/library/83y4ak54.aspx
有一些机制可以使一个无法访问的对象在垃圾收集中存活下来。
答案 2 :(得分:-1)
是
弱引用不会延长对象的生命周期,因此一旦所有强引用都超出范围,就允许对其进行垃圾回收。它们可用于保留初始化成本昂贵的大型对象,但如果它们没有被主动使用,则应该可用于garabage收集。