Поведение GC и захват потоков CLR
Я читал о GC в книге CLR via C#
, а именно о том, когда CLR хочет начать сбор. Я понимаю, что он должен приостанавливать потоки перед сборкой, но в ней упоминается, что она должна делать это, когда указатель инструкции потока достигает безопасной точки. В тех случаях, когда он не находится в безопасном месте, он пытается быстро добраться до него, и он делает это через hijacking
поток (вставка специального указателя функции в стек потока). Что все прекрасное и денди, но я думал, что управляемые потоки по умолчанию были в безопасности?
Первоначально я думал, что это может быть ссылка на неуправляемые потоки, но CLR позволяет неуправляемым потокам продолжать выполнение, потому что любой используемый объект должен был быть закреплен в любом случае.
Итак, что такое safe point
в управляемом потоке и как GC может определить, что это такое?
EDIT:
Я не думаю, что я был достаточно конкретным. Согласно этой статье MSDN, даже когда вызывается Thread.Suspend
, поток фактически не будет приостановлен до достижения safe point
. Далее указывается, что a safe point
является точкой в выполнении потоков, при которой может быть выполнена сборка мусора.
Я думаю, что я был неясен в своем вопросе. Я понимаю, что Thread можно приостановить только в безопасном месте, и их нужно приостановить для GC, но я не могу найти четкого ответа на вопрос о том, что такое безопасная точка. Что определяет точку в коде как безопасную?
Ответы
Ответ 1
"Безопасные точки" находятся там, где мы находимся:
- Не в блоке catch.
- Не внутри наконец
- Не внутри блокировки
-
Не внутри вызова p/invoke'd (в управляемом коде). Не выполняется неуправляемый код в среде CLR.
- Дерево памяти доступно.
Точка № 5 немного запутанна, но бывают случаи, когда дерево памяти не будет ходить. Например, после оптимизации CLR может создать новый объект и не назначать его непосредственно переменной. Согласно GC, этот объект будет мертвым объектом, готовым к сбору. Компилятор проинструктирует GC, когда это произойдет, чтобы еще не запустить GC.
Вот сообщение в блоге на msdn с немного дополнительной информацией: http://blogs.msdn.com/b/abhinaba/archive/2009/09/02/netcf-gc-and-thread-blocking.aspx
EDIT: Ну, сэр, я был НЕПРАВИЛЬНО о # 4. См. здесь в разделе "Безопасная точка". Если мы находимся внутри секции кода p/invoke (неуправляемый), тогда разрешено работать до тех пор, пока он снова не вернется в управляемый код.
Однако, согласно этой статье MSDN, если мы находимся в неуправляемой части кода CLR, тогда это не считается безопасным, и они будут ждать, пока код не вернется к управляемому. (Я был близок, по крайней мере).