ключевое слово блокировки в C #

Я понимаю основную функцию ключевого слова блокировки от MSDN

Заявление о блокировке (ссылка на C #)

Ключевое слово lock указывает блок оператора как критический раздел, получая блокировку взаимного исключения для данного объекта, выполняя инструкцию, а затем освобождая блокировку.

Когда следует использовать замок?

Например, это имеет смысл в многопоточных приложениях, поскольку защищает данные. Но нужно ли, когда приложение не выделяет другие streamи?

Есть ли проблемы с производительностью при использовании блокировки?

Я только что унаследовал приложение, которое использует блокировку повсюду, и оно однопоточное, и я хочу знать, должен ли я оставить их, они даже нужны?

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

Когда следует использовать замок?

Блокировка должна использоваться для защиты общих ресурсов в многопоточном коде. Ни для чего другого.

Но нужно ли, когда приложение не выделяет другие streamи?

Точно нет. Это просто потеря времени. Однако не забудьте, что вы неявно используете системные streamи. Например, если вы используете asynchronous ввод-вывод, вы можете получать обратные вызовы из случайного streamа, а не из вашего исходного streamа.

Есть ли проблемы с производительностью при использовании блокировки?

Да. Они не очень большие в однопоточном приложении, но зачем делать звонки вам не нужны?

… если это хорошая модель дизайна, которая будет следовать в будущем [?]

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

Все ответы здесь кажутся правильными: полезность замков заключается в том, чтобы блокировать streamи от одновременного блокирования кода. Однако в этом поле есть много тонкостей, одним из которых является то, что блокированные блоки кода автоматически помечены как критические регионы с помощью Common Language Runtime.

Эффект от маркировки кода как критического заключается в том, что если весь регион не может быть полностью выполнен, среда выполнения может считать, что весь ваш домен приложения потенциально подвержен опасности и, следовательно, выгружает его из памяти. Чтобы процитировать MSDN :

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

Поэтому, хотя ваше приложение однопоточное, это может быть опасно для вас. Учтите, что один метод в заблокированном блоке генерирует исключение, которое в конечном итоге не обрабатывается внутри блока. Даже если исключение обрабатывается по мере того, как оно пузырится через стек вызовов, ваша критическая область кода не заканчивается нормально. И кто знает, как CLR будет реагировать?

Для получения дополнительной информации прочитайте эту статью о опасностях Thread.Abort () .

Имейте в виду, что могут быть причины, по которым ваше приложение не является однопоточным, как вы думаете. Асинхронный ввод-вывод в .NET может также вызвать обратную связь в streamе пула, например, как и некоторые из различных classов таймера (но не Таймер Windows Forms).

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

блокировка должна использоваться вокруг кода, который изменяет общее состояние, состояние, которое одновременно изменяется другими streamами, и эти другие ступени должны иметь одинаковую блокировку.

Блокировка на самом деле является сериализатором доступа к памяти, streamи (которые принимают блокировку) будут ждать, пока блокировка будет введена до тех пор, пока текущий stream не выйдет из блокировки, поэтому доступ к памяти будет сериализован.

Чтобы ответить на вопрос, блокировка вопроса не требуется в однопоточном приложении и имеет побочные эффекты производительности. потому что блокировки на C # основаны на объектах синхронизации ядра, и каждая блокировка, которую вы берете, создает переход в режим ядра из пользовательского режима.

Если вы заинтересованы в многопоточной производительности, то хорошим местом для начала является руководство по streamам MSDN

У вас могут быть проблемы с производительностью с блокировкой переменных, но, как правило, вы строите свой код, чтобы свести к минимуму длительность времени, затраченного на блокировку кода.

Что касается удаления замков. Это будет зависеть от того, что именно делает код. Несмотря на то, что это однопоточно, если ваш объект реализован как Singleton, возможно, что у вас будет несколько клиентов, использующих его экземпляр (в памяти, на сервере) одновременно.

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

Использование блокировок (или любого другого оператора взаимного исключения или конструкции) обычно требуется только в многопоточных сценариях, где несколько streamов (либо вашего собственного создания, либо вашего вызывающего) имеют возможность взаимодействовать с объектом и изменять базовое состояние или данные сохранены. Например, если у вас есть коллекция, к которой можно получить доступ по нескольким streamам, вы не хотите, чтобы один stream менял содержимое этой коллекции, удаляя элемент, а другой stream пытается его прочитать.

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

И блокировка вызывает повышение производительности, добавляя инструкции для проверки на одновременный доступ до выполнения кода. Его следует использовать только там, где это необходимо.

См. Вопрос о «Mutex» в C #. Затем рассмотрите эти два вопроса относительно использования оператора «lock (Object)».

Нет смысла устанавливать блокировки в приложении, если есть только один stream, и да, это удар по производительности, хотя для этого удара требуется довольно много вызовов, чтобы вложить что-то значительное.

  • Может ли x86 переупорядочить узкий магазин с более широкой нагрузкой, которая полностью его содержит?
  • Безопасно ли использовать логический флаг, чтобы остановить stream из C #
  • Как использовать свойство CancellationToken?
  • Явная блокировка Java
  • Разрыв параллельный.
  • Как правильно прочитать поле Interlocked.Increment' int?
  • Монитор против Mutex в c #
  • Как Java использует несколько ядер?
  • kill -3, чтобы получить java thread dump
  • System.Threading.Tasks - ограничение количества одновременных задач
  • Использование памяти в C #
  • Давайте будем гением компьютера.