2012-01-27 9 views
5

This artykuł mówiDlaczego zajęcia z finalizatorami wymagają więcej niż jednego cyklu zbierania śmieci?

Jeśli obiekt ma finalizatora, nie jest natychmiast usuwany, gdy kolektor śmieci decyduje, że nie jest już „na żywo”. Zamiast tego staje się specjalnym rodzajem korzenia, dopóki .NET nie nazwał metody finalizatora. Oznacza to, że te obiekty zwykle wymagają więcej niż jednego śmiecia kolekcji, która ma zostać usunięta z pamięci, ponieważ przeżyją one pierwszy raz, gdy zostaną uznane za nieużywane.

Moje pytanie brzmi, dlaczego GC nie wywołuje finalizatora, gdy stwierdzi, że obiekt nie może być już odsyłany i od razu zbiera obiekt? dlaczego potrzebuje czegoś więcej niż tylko garbage collection?

Odpowiedz

6

dwa punkty do rozważenia:

  • Finalizer może zająć trochę czasu, aby zakończyć. Na przykład może to oznaczać zamknięcie zasobu lub coś podobnego. Nie chciałbyś, aby było to częścią czasu zbierania śmieci, które może blokować wątki przed robieniem pracy (kiedy chcą tylko zdobyć trochę pamięci). Kończąc osobną finalizację, sam GC może się bardzo szybko zakończyć, a prace nad finalizacją można wykonać równolegle z innymi pracami później.

  • Finalizator może wskrzesić obiekt, czyniąc go ponownie widocznym - ale wykrycie, że (co podejrzewam) i tak wymaga kolejnego przemiatania pamięci ... więc dlaczego nie poczekać, aż następnym razem się to stanie?

3

Ponieważ (w zależności od wybranego trybu GC) podczas wykonywania GC it has to pause key parts of the runtime. Dlatego chcesz, aby to było tak szybkie, jak to tylko możliwe. Stwarza to dwa problemy:

  1. nie wie, jak długo finalizator odbędzie się uruchomić (chociaż ma sztywny limit), a nie chce opóźnić wznowienie runtime
  2. runtime musi być uruchomiony za finalizatora działała niezawodnie (nawet jeśli stosuje się nić GC, kod piszesz mogłaby dbać o innych wątków)

aby rozwiązać oba problemy, osoby z toczących finalizatorów są w kolejce, a następnie stracony po GC został zakończony (gdy działa środowisko wykonawcze).

Na marginesie, dobrą praktyką jest łączenie finalizatorów z IDisposable i anulowanie finalizacji przez Dispose(); w ten sposób nie wymaga późniejszego finalizowania i jest czyszczony w jednym kroku.

0

Gdy NET śmieci kolektora pracuje obiekty są podzielone na trzy kategorie: obiektów, które są oddalone od „normalnego” odniesienia zakorzenione, przedmioty, które nie są osiągalne każdy korzenie odniesienia, i przedmioty, które nie można uzyskać dostępu za pomocą "normalnego" odwołania do zrootowanego, ale zażądano od niego powiadomienia, gdy są one porzucone, lub są dostępne z innych obiektów, które to zrobiły. Śmieciarz tworzy listę obiektów w tej trzeciej kategorii; ta lista jest przechowywana jako odniesienie zrootowane, dzięki czemu wszystkie obiekty w niej są "na żywo".System przechodzi przez pozycje z tej listy, anuluje żądania "powiadomień", uruchamia metodę Finalize() i usuwa je z listy. Jeśli nie ma nigdzie odniesienia do obiektu, gdy wszystko zostało powiedziane i zrobione, to obiekt zostanie ogłoszony "martwy" w następnym cyklu GC.

Powiązane problemy