Почему деструктор называют, когда сборщик "мусора" CPython отключен?

Я пытаюсь понять внутренности сборщика "мусора" CPython, конкретно когда деструктор называют. До сих пор поведение интуитивно, но следующий случай сбивает меня с толку:

  1. Отключите GC.
  2. Создайте объект, затем удалите ссылку на него.
  3. Объект уничтожается, и _____ del _____ метод называют.

Я думал, что это только произошло бы, если бы сборщик "мусора" был включен. Кто-то может объяснить, почему это происходит? Существует ли способ задержать вызов деструктора?

import gc
import unittest

_destroyed = False

class MyClass(object):

    def __del__(self):
        global _destroyed
        _destroyed = True

class GarbageCollectionTest(unittest.TestCase):

    def testExplicitGarbageCollection(self):
        gc.disable()
        ref = MyClass()
        ref = None
        # The next test fails. 
        # The object is automatically destroyed even with the collector turned off.
        self.assertFalse(_destroyed) 
        gc.collect()
        self.assertTrue(_destroyed)

if __name__=='__main__':
    unittest.main()

Отказ от ответственности: этот код не предназначен для производства - я уже отметил, что это является очень определенным для реализации и не работает над Jython.

6
задан Frederik 5 April 2010 в 11:28
поделиться

3 ответа

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

Поскольку после ref = None не осталось ссылок на ваш объект, его метод __ del __ вызывается в результате обнуления его счетчика ссылок.

В документации есть подсказка: «Поскольку сборщик дополняет подсчет ссылок, уже используемый в Python ...» (выделено мной).

Вы можете остановить срабатывание первого утверждения, заставив объект ссылаться на себя, чтобы его счетчик ссылок не обнулялся, например, передав ему этот конструктор:

def __init__(self):
    self.myself = self

Но если вы это сделаете, второе утверждение сработает. Это потому, что циклы мусора с методами __ del __ не собираются - см. Документацию для gc.garbage .

9
ответ дан 8 December 2019 в 13:45
поделиться

В зависимости от вашего определения сборщика мусора, CPython имеет два сборщика мусора: один, подсчитывающий ссылки, и другой.
Счетчик ссылок всегда работает, и его нельзя отключить, так как он довольно быстрый и легкий, который не оказывает существенного влияния на время работы системы.
Другой (по-моему, с некоторыми вариантами mark и sweep) запускается время от времени, и его можно отключить. Это связано с тем, что для этого требуется, чтобы интерпретатор был приостановлен во время его работы, а это может произойти в неподходящий момент и потреблять довольно много времени ЦП.
Эта возможность отключить его существует в то время, когда вы планируете делать что-то критичное по времени, и отсутствие этого GC не вызовет у вас никаких проблем.

4
ответ дан 8 December 2019 в 13:45
поделиться

Документы здесь объясняют, как то, что называется «необязательный сборщик мусора», на самом деле является сборщиком циклического мусора. (такой, который не учитывается при подсчете ссылок). Подсчет ссылок объясняется здесь , с намеком на его взаимодействие с циклическим gc:

Хотя Python использует традиционную реализацию подсчета ссылок , он также предлагает цикл детектор, который работает для обнаружения эталонных циклов. Это позволяет приложениям не беспокоиться о создании прямых или косвенных циклических ссылок; это слабость сборки мусора, реализованной с использованием только подсчета ссылок. Циклы ссылок состоят из объектов, которые содержат (возможно, косвенные) ссылки на самих себя, так что каждый объект в цикле имеет счетчик ссылок, который {{1} }} не равно нулю. Типичные реализации подсчета ссылок не могут освободить память, принадлежащую каким-либо объектам в цикле ссылок или , на которые ссылаются объекты в {{1} }} цикл, даже если нет никаких дополнительных ссылок на сам цикл .

4
ответ дан 8 December 2019 в 13:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: