Подтвердить что ты не робот

Почему "lock (typeof (MyType))" проблема?

MSDN предоставляет следующее предупреждение о ключевом слове блокировка в С#:

В общем, избегайте блокировки публичного тип или экземпляры, выходящие за рамки вашего кода. контроль. Замок общих конструкций (это), lock (typeof (MyType)) и lock ( "myLock" ) нарушают это руководство:

* lock (this) is a problem if the instance can be accessed publicly.
* lock (typeof (MyType)) is a problem if MyType is publicly accessible.

Но это не дает веских оснований для этого. Блокировка (это) объясняется здесь на SO. Меня интересует случай блокировки (typeof (MyType)). Что в этом опасно?

Спасибо.

4b9b3361

Ответ 1

Это опасно, потому что что-то может занять этот замок, поэтому трудно или невозможно предотвратить ситуацию взаимоблокировки.

Раньше была статья об этом ( "Do not Lock Type Objects!" статья доктора GUI) с некоторыми комментариями Рико Мариани. По-видимому, статья уже недоступна, но есть "зеркала", плавающие вокруг, в том числе http://bytes.com/topic/c-sharp/answers/249277-dont-lock-type-objects.

Здесь выдержка:

Основная проблема заключается в том, что вы не являетесь владельцем объекта type, и вы не знаете, кто еще может получить к нему доступ. В общем, очень плохая идея полагаться на блокировку объекта, который вы не создали, и не знаете, к кому еще можно получить доступ. Это делает тупик. Самый безопасный способ - заблокировать частные объекты.

Но подождите; это даже хуже всего. Как оказалось, объекты типа иногда передаются между доменами приложений (но не через процессы) в текущих версиях среды выполнения .NET. (Это нормально, так как они неизменяемы.) Это означает, что возможно, что ДРУГОЕ ЗАЯВЛЕНИЕ работает даже в другом домене приложения (но в том же процессе), чтобы затормозить ваше приложение, получив блокировку объекта типа, который вы хотите заблокировать и никогда не выпускал его. И было бы легко получить доступ к этому типу, потому что у объекта есть имя - полное имя типа! Помните, что блокировка /SyncLock блокирует (что вежливое слово для зависания), пока оно не сможет получить блокировку. Очевидно, что очень плохо полагаться на блокировку, которую может заблокировать другая программа или компонент, и заставить вас зайти в тупик.

Ответ 2

Это та же проблема, что и с lock(this) - вы блокируете ссылку, к которой имеет доступ другой код, поэтому она также может блокироваться.

Если у вас есть две несвязанные части кода, блокирующие одну и ту же ссылку, не намереваясь исключать друг друга, тогда в лучшем случае вы можете потерять немного производительности из-за отсутствия concurrency - и в худшем случае вы может ввести тупик.

Ответ 3

Потому что результат typeof (MyType) (который является объектом типа Type) широко доступен, а другой поток может блокировать один и тот же объект и удерживать эту блокировку неограниченно долго. Тогда внутренняя логика MyType эффективно избавила от значительного контроля над логикой синхронизации. Это может быть не актуальной проблемой, если это предназначено, но кодирование защитно/скептически должно быть вашим modus operandi.

Ответ 4

потому что цель блокировки ТОЛЬКО для установки места для хранения блокировки boolean (Я заблокирован или нет) для других потоков, чтобы посмотреть....

Распространенное заблуждение о том, что цель блокировки на самом деле как-то заблокирована, просто неверна... Что такое "заблокировано",... ничего, если только в тех методах, которые могут получить доступ к некоторой разделяемой памяти небезопасным образом, вы пишете код, чтобы посмотреть на эту блокировку и не продолжать, пока она не будет выпущена... с использованием объекта типа, поскольку цель блокировки неверна, потому что фрагменты кода в любом месте всего пространства процесса решения могут получить доступ к этому типу объекта и изменить блок синхронизации, в котором хранится логическое значение блокировки. Создание объекта с локальным областью позволяет лучше гарантировать, что только те потоки и методы, которые могут получить доступ или могут взаимодействовать с вашей общей памятью "в опасности", могут также получить доступ и/или изменить блокировку.

Ответ 5

Также указывается документация по теме "Рекомендации по управляемой потоковой передаче". https://msdn.microsoft.com/en-us/library/1c9txz50(v=vs.110).aspx

В нем говорится:

Не используйте типы в качестве объектов блокировки. То есть избегайте использования кода, такого как lock (typeof (X)) в С# или SyncLock (GetType (X)) в Visual Basic или использование объекта Monitor.Enter с типом. Для данного типа существует только один экземпляр System.Type для домена приложения. Если тип вы берете блокировку, является общедоступной, другой код, кроме вашего, может принимать блокировки на нем, что приводит к взаимоблокировкам. Дополнительные вопросы см. Надежность Лучшие практики.

Соблюдайте осторожность при блокировке экземпляров, например lock (this) на С# или SyncLock (Me) в Visual Basic. Если в вашем приложении используется другой код, внешний по отношению к типу, блокирует объект, блокировки могут происходят.