Действительно ли слабые ссылки на 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
Это позволяет отфильтровывать мертвые слабые ссылки и добавлять новую в начало связанного списка, каждый раз распечатывая длину списка. На моей машине это никогда не превышает 1000 выживших слабых ссылок. Он нарастает, а затем падает до нуля в циклах, предположительно, потому что все слабые ссылки собираются в каждой коллекции gen0. Опять же, это поведение слабой ссылки, а не мягкой ссылки.
Обратите внимание, что именно это поведение (агрессивная коллекция объектов со слабыми ссылками в коллекциях gen0) как раз и делает слабые ссылки плохим выбором для кэшей. Если вы попытаетесь использовать слабые ссылки в своем кеше, то обнаружите, что ваш кэш часто сбрасывается без всякой причины.