2010-12-11 2 views
9

Темы в .NET приостановлены во время GC. Как можно безопасно приостановить поток с помощью CLR? Что может быть риском, останавливая поток жестоким способом, например Win32 SuspendThread API?Безопасная приостановка потока во время GC в .NET

+0

Вам не нужно думать о сборке мусора в .NET, и вам, разумеется, не нужно вручную приостанавливать свои собственные потоки во время его возникновения. .NET позаботится об этом для вас совершенно прозрачным способом. – Juliet

+2

Я знаю. Вопрос о том, как CLR это делает? – Ostap

+0

Интересный вопрос. – Steven

ответ

7

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

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

+0

Спасибо за ответ! – Ostap

5

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

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

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

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

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

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

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

Имеет смысл?

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

+0

Отлично! Благодарю . – Ostap

Смежные вопросы