Являются ли C # слабые ссылки на самом деле мягкими? - PullRequest
18 голосов
/ 13 октября 2011

Основное различие заключается в том, что слабые ссылки должны быть востребованы при каждом запуске ГХ (сохранить объем памяти), в то время как мягкие ссылки должны храниться в памяти до тех пор, пока ГХ фактически не потребует память (они пытаются увеличить время жизни, но могут потерпеть неудачу в любое время, что полезно, например, для кеширования, особенно дорогих объектов).

Насколько мне известно, нет четкого заявления о том, как слабые ссылки влияют на время жизни объекта в .NET. Если они действительно слабые реферы, они вообще не должны на это влиять, но это также сделало бы их довольно бесполезными для их, я полагаю, основной цели кеширования (я там ошибаюсь?). С другой стороны, если они действуют как мягкие рефери, их имя немного вводит в заблуждение.

Лично я представляю, что они ведут себя как мягкие ссылки, но это просто впечатление, а не основание.

Детали реализации применимы, конечно. Я спрашиваю о менталитете, связанном со слабыми ссылками .NET - они способны продлить срок службы или ведут себя как настоящие слабые рефери?

(Несмотря на ряд связанных вопросов, я пока не смог найти ответ на этот конкретный вопрос.)

Ответы [ 3 ]

13 голосов
/ 07 января 2013

Действительно ли слабые ссылки на 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) как раз и делает слабые ссылки плохим выбором для кэшей. Если вы попытаетесь использовать слабые ссылки в своем кеше, то обнаружите, что ваш кэш часто сбрасывается без всякой причины.

8 голосов
/ 13 октября 2011

Я не видел информации, указывающей на то, что они увеличат время жизни объекта, на который они указывают.И статьи, которые я читал об алгоритме, который GC использует для определения достижимости, также не упоминают их таким образом.Поэтому я ожидаю, что они не будут влиять на время жизни объекта.

Слабый Этот тип дескриптора используется для отслеживания объекта, но позволяет его собирать.Когда объект собран, содержимое GCHandle обнуляется.Слабые ссылки обнуляются перед запуском финализатора, поэтому, даже если финализатор воскресит объект, Слабая ссылка все еще обнуляется.

WeakTrackResurrection Этот тип дескриптора похож на Weak, но дескриптор не обнуляется, если объект воскресает во время финализации.

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


Существует несколько механизмов, с помощью которыхнедоступный объект может пережить сборку мусора.

  • Генерация объекта больше, чем генерация GC, которая произошла.Это особенно интересно для больших объектов, которые размещаются в куче больших объектов и всегда считаются Gen2 для этой цели.
  • Объекты с финализатором и все объекты, достижимые из них, выживают в GC.
  • Возможно, существует механизм, при котором прежние ссылки со старых объектов могут поддерживать жизнь молодых объектов, но я не уверен в этом.
0 голосов
/ 13 октября 2011

Да Слабые ссылки не увеличивают срок службы объекта, что позволяет собирать мусор после того, как все сильные ссылки вышли из области видимости.Они могут быть полезны для удержания больших объектов, которые дороги для инициализации, но должны быть доступны для сбора мусора, если они не используются активно.

...