Сборщик мусора и круговая ссылка - PullRequest
55 голосов
/ 12 января 2012

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

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 выходит из области видимости, и сборщик мусора должен иметь возможность его собрать., но если бы он собирал его, ему нужно было бы сначала собрать a, который является членом B, а чтобы собрать a, ему нужно сначала собрать b, который является членом A,Это становится круглым.Поэтому мой вопрос: собирается ли такая круговая ссылка помешать GC собирать объекты?

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

Ответы [ 4 ]

85 голосов
/ 12 января 2012

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

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

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

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

30 голосов
/ 12 января 2012

Нет, это не будет проблемой, потому что GC может обрабатывать циклические ссылки

MSDN говорит

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

5 голосов
/ 12 января 2012

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

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

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

5 голосов
/ 12 января 2012

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

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

...