Поведение GC и угон потока CLR - PullRequest
13 голосов
/ 06 декабря 2011

Я читал о GC в книге CLR via C#, особенно о том, когда CLR хочет начать сбор. Я понимаю, что он должен приостановить потоки до того, как произойдет сбор, но он упоминает, что должен делать это, когда указатель инструкции потока достигает безопасной точки. В тех случаях, когда он находится в небезопасной точке, он пытается быстро добраться до него и делает это путем hijacking потока (вставляя специальный указатель функции в стек потока). Это все прекрасно, но я думал, что управляемые потоки по умолчанию безопасны?

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

Итак, что такое safe point в управляемом потоке и как GC может определить, что это такое?

EDIT:

Не думаю, что я был достаточно конкретен. Согласно этой статье MSDN , даже когда вызывается Thread.Suspend, поток фактически не будет приостановлен, пока не будет достигнут safe point. Далее следует, что safe point - это точка выполнения потоков, в которой может выполняться сборка мусора.

Мне кажется, я был неясен в своем вопросе. Я понимаю, что поток может быть приостановлен только в безопасной точке, и они должны быть приостановлены для GC, но я не могу найти четкого ответа относительно того, что такое безопасная точка. Что определяет точку в коде как безопасную?

1 Ответ

14 голосов
/ 06 декабря 2011

«Безопасные пункты» - это то, где мы находимся:

  1. Не в блоке улова.
  2. Не внутри наконец
  3. Не внутри замка
  4. Не внутри вызова p / invoke'd (в управляемом коде). Не запускать неуправляемый код в CLR.
  5. Дерево памяти доступно для прохождения.

Точка # 5 немного сбивает с толку, но бывают случаи, когда дерево памяти не будет доступным. Например, после оптимизации CLR может создать новый объект и не назначать его непосредственно переменной. Согласно GC, этот объект будет мертвым объектом, готовым для сбора. Компилятор проинструктирует GC, когда это случится, еще не запускает GC.

Вот сообщение в блоге на msdn с немного большей информацией: http://blogs.msdn.com/b/abhinaba/archive/2009/09/02/netcf-gc-and-thread-blocking.aspx

РЕДАКТИРОВАТЬ: Ну, сэр, я был не прав насчет # 4. См. здесь в разделе «Безопасная точка». Если мы находимся внутри секции кода p / invoke (неуправляемой), то она может работать до тех пор, пока снова не вернется к управляемому коду.

Однако, согласно этой статье MSDN , если мы находимся в неуправляемой части кода CLR, то это не считается безопасным, и они будут ждать, пока код не вернется к управляемому. (Я был близко, по крайней мере).

...