Как говорит Хольгер в комментарии , вопрос не совсем правильно сформулирован. Ваш вопрос также предполагает сбор на основе подсчета ссылок , который не совсем подходит для циклических структур данных, например ::10000
class LinkedList(object):
def __init__(self, next = None):
self.next = next
def set_next(self, next):
self.next = next
...
e1 = LinkedList()
e2 = LinkedList(e1)
e1.set_next(e2)
(выражено в Python). Что такое счетчик ссылок для e1, когда e1.next.next также равен e1, так что e1.next.next.next равен e1 и т. Д.? (Или, проще говоря, что если мы установим e1.next для самого e1?)
Традиционная сборка мусора на Lisp началась с Алгоритмы Mark и Sweep (Примечание: я не знаю, хорош ли этот веб-сайт в целом, но я отсканировал связанную статью и, кажется, все в порядке). Современные системы часто имеют более замысловатые схемы, такие как сбор из поколения в поколение, «живой» (многопоточный) сбор вместо «останови и работай» и сбор в реальном времени. См. основную статью в Википедии и особенно более полную статью «Сборка мусора» статью.
Обратите внимание, что ключевое различие между сильной ссылкой и слабой ссылкой заключается в том, что сильная ссылка равна , которая учитывается при анализе живучести, т. Е. При определении того, стоит ли держать некоторый объект рядом, потому что этого хочет другой объект - и слабой ссылки нет. Самый классический пример, который я знаю, где требуется слабая ссылка, - это поисковый кеш , где есть некоторая сложная структура данных, такая как база данных на основе B-дерева на диске или аналогичная, где некоторые объекты может быть занесено в память для использования на некоторое время, и мы хотели бы иметь быстрый способ выяснить, доступны ли они еще: dictionary[key]
будет быстрой, но слабой ссылкой на объект, в то время как database.load(key)
возвращает сильную ссылку на объект, возможно, после загрузки.
Многие детали реализации проистекают из таких вопросов, как то, позволяет ли сам язык использовать и работать с указателями. Языки с манипулированием указателями (такие как C ++) затрудняют анализ во время компиляции, что упрощают другие языки (такие как Go).
Блог Майка Эша , из Комментарий Мартина Р. , содержит краткое изложение некоторых из этих проблем и фактических реализаций, включая две, использованные в Swift.
Язык Go использует escape-анализ , чтобы выделить некоторые объекты в стеке, а другие - в кучу для сбора мусора.