В приложении ASP.NET у меня есть ресурс, защищенный ReaderWriterLockSlim.
Обычные запросы вызывают EnterReadLock, обращаются к ресурсу, вызывают ExitReadLock и возвращаются.
В какой-то момент я случайно забыл поставить вызов ExitReadLock где-то в своем коде. На следующий запрос я получил исключение о том, что поток уже вошел в блокировку.
Достаточно справедливо: если в конце запроса A поток не выходит из блокировки, и этот же поток используется для обработки запроса B и пытается войти в блокировку, он будет сброшен.
Теперь мой вопрос: возможен ли следующий сценарий? причины?
- поток начинает обрабатывать запрос A
- поток входит в замок
- поток, скажем, спит или выполняет какой-то ввод-вывод, и поэтому становится доступным
- тот же поток начинает обрабатывать запрос B, в то время как запрос A находится в состоянии ожидания.
- поток входит в блокировку !! бросает!!
Если да, какое другое решение у меня есть для защиты указанного ресурса? Имея в виду, что я хочу использовать ReaderWriterLockSlim, потому что у меня также есть другой поток, который может записывать в ресурс?
изменить: добавить некоторые детали:
1) Это происходит в методе ProcessRequest HttpHandler, который генерирует, кэширует и обслуживает изображения. Эти изображения дорого генерировать. Таким образом, первый запрос будет генерировать и кэшировать изображение, и мы хотим приостановить другие запросы во время генерации.
2) Мы не пытались "воспроизвести" - в данный момент мы пытаемся узнать, возможно ли, чтобы тот же поток начал обработку запроса, уже ожидая, пока изображение станет готов.
3) Мне известно о LockPolicyRecursion, но я не уверен, что полностью понимаю его назначение, и можно ли в нашем случае установить для него значение SupportsRecursion.
изменить: идем дальше...
Согласно документу, указанному Райаном ниже, поток блокируется и не возвращается в пул, пока мы не выполняем асинхронные операции. Поэтому, как только мы заблокировали поток, ожидающий завершения EnterReadLock, он не вернется в пул и не обработает какой-либо другой запрос.
Итак, 1) мы должны быть в безопасности, но 2) мы можем голодать в пуле потоков. Предполагая, что мы не хотим немедленно возвращать фиктивное изображение «пожалуйста, подождите», какие у нас есть решения?
2 ответа
Да, это возможно в ASP.NET. Есть некоторые места (асинхронные и т. д.), где ASP.NET выполняет переключение потоков и использует разные потоки для одного запроса (в разных точках), что означает, что вполне возможно, что на полпути через запрос этот поток переходит к обработке < em>другой запрос.
В каких точках конвейера вы берете/отпускаете блокировку? Вы можете уменьшить это? Лично я бы ограничил продолжительность потока некоторым синхронным методом, который отделен от кода пользовательского интерфейса/представления. Он не будет менять потоки в середине синхронного метода.
Поток, заблокированный для чтения, который повторно используется пулом, определенно может повторно войти в блокировку, если он запрашивает чтение. Может ли пул повторно использовать заблокированный для чтения поток? В этом я не уверен, но операция чтения должна быть достаточно быстрой, чтобы избежать состояния гонки.
Пул потоков должен освобождать поток только в том случае, если он простаивает (т. е. находится в спящем режиме). Таким образом, вы ожидаете, что если ваш защищенный код не приводит к бездействию потока, то поток не должен освобождаться, пока он находится в блокировке — просто убедитесь, что вы выходите из блокировки (всегда выйти в блоке finally
)
Если вы хотите убедиться, что вы не входите в блокировку повторно, вам нужно заблокировать поток с помощью монитора (или блокировки записи); блокирующие потоки не возвращаются в пул.
РЕДАКТИРОВАТЬ: если вы создаете изображения, вы должны получить блокировку записи, которая заблокирует все блокировки чтения. Ни блокирующие, ни заблокированные потоки не будут использоваться повторно, поэтому у вас не должно возникнуть проблем.
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.