Как правило, поток 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).
Имеет смысл?
Счастливого взлома!