Подтвердить что ты не робот

Сборщик мусора и циркулярная ссылка

Рассмотрим эти два класса:

public class A
{
     B b;
     public A(B b) { this.b = b; }
}

public class B
{
     A a;
     public B() { this.a =  new A(this); }
}

Если у меня есть классы, созданные выше, будут ли объекты таких классов собираться сборщиком мусора (GC)?

Предположим, что я делаю это:

void f()
{
     B b = new B();
}

В этом методе я создаю экземпляр B, называемый B, и когда метод возвращается, B выходит за пределы области видимости, и GC должен иметь возможность собирать его, но если он должен собирать он должен был бы сначала собрать a, который является членом B, и собрать a, ему нужно сначала собрать B, который является членом a. Он становится круговым. Поэтому мой вопрос: является ли такая циркулярная ссылка предотвращением сбора объектов GC?

  • Если да, то как мы можем избежать этой проблемы? Как мы можем убедиться, что у нас нет круговой ссылки в нашем классе? Есть ли какой-либо инструмент (или параметр компилятора), который помогает нам обнаруживать циклическую ссылку?
  • Если нет, где и почему мы используем класс WeakReference? Какова его цель?
4b9b3361

Ответ 1

Сборщик мусора .Net может абсолютно обрабатывать циклические ссылки. Высокий уровень очень того, как работает сборщик мусора,...

  • Начните с locals, statics и GC закрепленных объектов. Ни одно из них не может быть собрано.
  • Отметьте каждый объект, который может быть достигнут путем перемещения детей этих объектов.
  • Соберите каждый объект, который не отмечен.

Это позволяет собирать круговые ссылки только штрафа. Пока ни один из них не может быть достигнут от объекта, который, как известно, является невообразимым, тогда круговая ссылка по существу не имеет значения.

Примечание. Я понимаю, что я упустил много интересных деталей, чтобы этот ответ был простым и прямым.

Ответ 2

Нет, это не будет проблемой, потому что GC может обрабатывать Circular References

MSDN говорит

Если группа объектов содержит ссылки друг на друга, но ни одна из эти объекты прямо или косвенно ссылаются на стек или общие переменные, а затем на мусор коллекция автоматически восстановит память.

Ответ 3

Несколько ответов уже объяснили, что круговые ссылки не являются проблемой.

Что касается слабых ссылок - причина их использования - кеширование.

Когда GC ходит по деревьям зависимостей объектов, он игнорирует слабые ссылки. Другими словами, если единственная ссылка на объект является слабым (ым), это будет сбор мусора, но если бы не было сбора мусора между созданием ссылки и вашей попыткой использования, вы все равно можете получить доступ к объекту.

Ответ 4

Нет, что круговая ссылка не повлияет на сборщик мусора, и она будет в полной мере способна собрать экземпляр B.

Сборщик мусора знает, что никто не может ссылаться на экземпляр B после выхода из сферы действия, и, следовательно, никто не может использовать экземпляр B, чтобы косвенно ссылаться на A.