Почему "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)). Что в этом опасно?
Спасибо.
Ответы
Ответ 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. Если в вашем приложении используется другой код, внешний по отношению к типу, блокирует объект, блокировки могут происходят.