Безопасная приостановка потока во время GC в .NET - PullRequest
9 голосов
/ 11 декабря 2010

Потоки в .NET приостановлены во время GC. Как CLR может безопасно приостановить поток? В чем может быть риск, если жестко остановить поток, такой как Win32 SuspendThread API?

Ответы [ 2 ]

7 голосов
/ 11 декабря 2010

Речь идет о .NET Compact Framework, но я думаю, что это правильно для нормального .NET: http://blogs.msdn.com/b/abhinaba/archive/2009/09/02/netcf-gc-and-thread-blocking.aspx

Перед тем, как фактически запустить GC, CLR пытается перейти в «безопасную точку».С каждым потоком связано событие приостановки, и это событие регулярно проверяется каждым потоком.Перед запуском GC CLR перечисляет все управляемые потоки и в каждом из них устанавливает это событие.В следующей точке, когда поток проверяет и находит этот набор событий, он блокирует ожидание сброса события (что происходит после завершения GC).

5 голосов
/ 11 декабря 2010

Как правило, поток 1 может безопасно приостановить поток 2, установив флаг «Пожалуйста, приостановите сейчас», согласно которому выполнение кода в потоке 2 гарантированно будет проверено в течение ограниченного периода времени, а затем приостановит себя в безопасной точке в его исполнение.

В .NET CLR (так оно и было раньше), что поток может находиться в кооперативном режиме GC или в режиме вытеснения. В кооперативном режиме, например при запуске методов управляемого кода поток иногда явно проверяет, должен ли он дать результат.

Напротив, в упреждающем режиме, например, при запуске собственного кода, вызванного p, а иногда и в самом CLR (MSCORWKS.DLL и т. д.), другой поток (включая другой поток CLR, необходимый для GC) может в одностороннем порядке приостановить первый поток на любой границе инструкции.

Действительно, их можно комбинировать. CLC GC может установить флаг «пожалуйста, приостановите сейчас», а затем подождать некоторое время, если поток с преимущественным режимом возвращается в кооперативный режим (который затем проверяет флаг и приостанавливает свой поток). Если после ожидания поток с преимущественным режимом все еще не приостановлен, CLR (в другом потоке) может в одностороннем порядке приостановить его.

При запуске метода .NET в кооперативном режиме сгенерированный нативный код зависит от гарантий отсутствия прерываний в кооперативном режиме для наиболее эффективной работы с памятью объекта (кучи GC и т. Д.). Если бы вы должны были внешне и «жестоко» приостановить совместный поток GC в произвольной точке его выполнения, он мог бы оставить память объекта или другие внутренние компоненты CLR в состоянии, которое может не подходить для правильного цикла сборки мусора или других операций CLR. , Но на практике этого никогда не происходит, потому что потоки кооперативного режима не приостанавливаются.

(Очевидно, что в некоторых случаях, когда поток кооперативного режима завершает свой квант планировщика потока ОС, а контекст ОС переключает это ядро ​​на какой-то другой поток. Поскольку поток больше не работает, он не опрашивает флаг yield, и не даст сразу. Я не помню, что происходит в таких случаях - должен ли CLR ждать, пока не будет перепланировано, проверяет флаг и дает, или же он все равно приостанавливает поток и затем проверяет свой IP для посмотреть, было ли это в безопасном месте. Кто-нибудь?)

Я полагаю, что это описано во внутренних органах SSCLI (Rotor).

Имеет смысл?

Счастливого взлома!

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