Какой смысл в сборщике мусора - PullRequest
3 голосов
/ 21 октября 2008
SqlConnection connection = new SqlConnection(FROM_CONFIGURATION) 
SqlCommand command = new SqlCommand("SomeSQL", connection); 
connection.Open(); 
command.ExecuteNonQuery(); 
command.Dispose(); 
connection.Dispose();

Рекомендуется, чтобы приведенный выше код включал try / catch (или using), чтобы в случае возникновения исключения все ресурсы располагались правильно.

Но если вам приходится беспокоиться об утилизации вещей вручную, тогда какой смысл в GC ?! Разве GC не позаботится об этом для кодера?

Ответы [ 15 ]

15 голосов
/ 21 октября 2008

Как и другие люди здесь говорили, что ГХ недетерминирован, поэтому вы не знаете, когда будет собран ваш объект. Я хочу уточнить, что это проблема не с памятью, а с системными ресурсами (открытыми файлами, соединениями с базой данных), которые дороги и должны быть освобождены как можно скорее. Dispose позволяет вам делать это, когда вы знаете, что больше не используете соединение. Если они не будут выпущены вовремя, система может исчерпать эти ресурсы, и GC не знает об этом. Вот почему вы должны сделать это вручную.

Также я хочу добавить, что использование выражения «using» сделает это за вас.

7 голосов
/ 21 октября 2008

Сборка мусора предназначена для освобождения неиспользованной памяти .

Существуют различные причины, по которым расширение GC для освобождения других ресурсов проблематично. Одним из них является то, что финализаторы (методы, которые выполняются, когда объект собирается для сбора мусора) делают ссылочные циклы несобираемыми, если только вы строго не ограничите разыменование из финализаторов, что делает их очень сложными в использовании.

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

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

И еще одна причина в том, что в некоторых приложениях GC ускоряет работу приложения, поскольку уменьшает количество копий, выполняемых для удовлетворения семантики владения. Что не касается других ресурсов.

Другие люди могли бы так продолжаться часами.

6 голосов
/ 21 октября 2008

Но если вам нужно беспокоиться о выбрасывать вещи вручную, тогда что точка GC ?! Там нет GC позаботиться об этом для кодера?

Проблема в том, что вы не представляете , когда запустит ГХ. И если ваше приложение никогда не будет загружать память, оно может вообще не работать.

5 голосов
/ 21 октября 2008

Предположим, у меня есть этот код:

class MonkeyGrabber : IDisposable {
   public MonkeyGrabber() { /* construction grabs a real, live monkey from the cage */
   public void Dispose() { Dispose(true); /* releases the monkey back into the cage */ }
   // the rest of the monkey grabbing is left as an exercise to grad student drones
}

class MonkeyMonitor {
    public void CheckMonkeys() {
        if (_monkeyPool.GettingTooRowdy()) {
            MonkeyGrabber grabber = new MonkeyGrabber();
            grabber.Spank();
        }
    }
}

Теперь, мой MonkeyMonitor проверяет обезьян и, если они слишком шумные, он получает ценный системный ресурс - единственный коготь обезьяны, прикрепленный к системе, и использует его, чтобы схватить обезьяну и отшлепать ее. Так как я не избавился от нее, обезьяний коготь все еще держит обезьяну, висящую над остальной клеткой. Если остальные обезьяны продолжат хулиганить, я не смогу сделать новый MonkeyGrabber, так как он все еще помогает. К сожалению. Придуманный пример, но вы понимаете: объекты, которые реализуют IDisposable, могут удерживать ограниченные ресурсы, которые должны быть выпущены своевременно. GC может отпустить в конце концов или нет.

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

Подробнее об IDisposable .

использует ваш друг - это самое близкое, что мы имеем до RAII .

4 голосов
/ 21 октября 2008

Объекты, которые реализуют IDisposable, пытаются сказать вам, что у них есть связи со структурами, которые не являются управляемой памятью. Сборщик мусора работает партиями для повышения эффективности. Но это означает, что может пройти некоторое время, прежде чем ваш объект будет удален, а это означает, что вы будете удерживать ресурсы дольше, чем должны, что может отрицательно сказаться на производительности / надежности / масштабируемости.

3 голосов
/ 21 октября 2008

GC запускается время от времени и заботится об управлении памятью, сохраняя все аккуратным и аккуратным для вас. Вы можете подумать, что это бесполезно, когда вы видите фрагменты кода, подобные тому, который вы разместили, но чаще всего это избавляет вас от многих головных болей (например, ручное управление памятью на C / C ++), поскольку значительно уменьшает утечки памяти и позволяет вам беспокоиться о том, как будет работать ваше приложение, а не о том, как вы будете управлять памятью. Утилизация файловых дескрипторов и соединений с базами данных является способом повышения эффективности, поскольку сборка мусора не является детерминированной и может произойти не сразу, и вы не хотите, чтобы эти файловые дескрипторы и открытые соединения с базами данных снижали производительность вашей системы. Кстати, ваш код действительно ужасен, я всегда поддерживаю оператор using и часто пишу свой код в БД, например:

using (SqlConnection connection = new SqlConnection(...))
using (SqlCommand command = connection.CreateCommand())
{
   ...
}

Это автоматически вызывает dispose для объектов соединения и команды, когда они выходят из области видимости, когда выполнение покидает блок.

2 голосов
/ 22 октября 2008

... GC никогда не предназначался для управления ресурсами; это было разработано, чтобы управлять распределением памяти ... В конкретном случае соединений с базой данных вы имеете дело с другими ресурсами, а не только с памятью ... (Скотт Дорман)

ОП не помечался конкретной платформой, хотя большинство ответов были специфичными для .net, отмечая, что GC в основном предназначен для предотвращения утечек памяти, но могут помочь такие расширения, как using выражения и IDisposable много.

Другие платформы предлагают другие решения. Например, в C ++ нет (встроенной) сборки мусора, но некоторые формы общих указателей могут использоваться для управления памятью, а стиль кодирования RAII может быть чрезвычайно полезен для управления другими типами ресурсов.

В cPython используются две разные системы сбора мусора. Реализация подсчета ссылок немедленно вызывает деструкторы при удалении последней ссылки. Для обычных «стековых» объектов это означает, что они немедленно очищаются, как это происходит с объектами C ++ RAII. Недостатком является то, что если у вас есть цикл ссылок, коллектор подсчета ссылок никогда не избавится от объекта. В результате у них есть вторичный недетерминированный сборщик мусора, который работает как сборщики Java и .NET. Как и .NET со своими операторами using, cPython пытается обрабатывать наиболее распространенные случаи.

Итак, чтобы ответить на OP, недетерминированная сборка мусора помогает упростить управление памятью, ее можно использовать и для обработки других ресурсов, если своевременность не является проблемой, и другой механизм (такой как тщательное программирование, подсчет ссылок GC, оператор использования или реальные объекты RAII) необходимы, когда требуется своевременное освобождение других ресурсов.

2 голосов
/ 21 октября 2008

Поскольку GC не самый эффективный - это не всегда происходит, как только ресурс больше не используется. Поэтому, когда вы имеете дело с неуправляемыми ресурсами, такими как файловый ввод-вывод, соединения с БД и т. Д., Рекомендуется освободить / очистить эти ресурсы, прежде чем ждать и полагаться на GC, чтобы позаботиться об этом.

И посмотрите на использование ключевого слова using:

using (SqlConnection connection = new SqlConnection(FROM_CONFIGURATION))
using (SqlCommand command = new SqlCommand("SomeSQL", connection))
{
  connection.Open(); 
  command.ExecuteNonQuery(); 
  command.Dispose(); 
  connection.Dispose();
}

Также, как правило, все, что может быть удалено, должно быть в блоке using.

1 голос
/ 22 октября 2008

Ах, теперь я вижу. Я перепутал управление памятью с неуправляемым управлением ресурсами. Спасибо за разъяснения!

1 голос
/ 21 октября 2008

Сборщик мусора (GC) в .NET является основной частью .NET Common Language Runtime (CLR) и доступен для всех языков программирования .NET. GC никогда не предназначался для управления ресурсами; он был разработан для управления распределением памяти и отлично справляется с управлением памятью, выделенной непосредственно для собственных объектов .NET. Он не предназначен для работы с неуправляемой памятью и выделенной памятью операционной системы, поэтому ответственность за управление этими ресурсами ложится на разработчика.

В конкретном случае соединений с базой данных вы имеете дело с другими ресурсами, а не только с памятью - в частности, с пулами соединений, возможными неявными областями транзакций и т. Д. Вызывая Close () и / или Dispose (), вы явно указываете объекту немедленно освободите эти неуправляемые ресурсы, пока управляемые ресурсы будут ожидать цикла GC.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...