Тупики трудно найти и очень неудобно удалить.
Как найти источники ошибок для взаимоблокировок в моем коде? Существуют ли "шаблоны блокировки"?
В моем специальном случае речь идет о базах данных, но этот вопрос открыт для каждого тупика.
Тупики трудно найти и очень неудобно удалить.
Как найти источники ошибок для взаимоблокировок в моем коде? Существуют ли "шаблоны блокировки"?
В моем специальном случае речь идет о базах данных, но этот вопрос открыт для каждого тупика.
Обновление. Эта недавняя статья MSDN, Инструменты и методы для определения Concurrency Вопросы, также может быть интересна
Стивен Туб в статье MSDN Монитор взаимоблокировки устанавливает следующие четыре условия, необходимые для возникновения взаимоблокировок:
Ограниченное количество определенного ресурса. В случае монитора на С# (то, что вы используете при использовании ключевого слова блокировки) это ограниченное число - одно, поскольку монитор является блокировкой взаимного исключения (это означает, что только один поток может одновременно иметь монитор).
Возможность удерживать один ресурс и запрашивать другой. В С# это похоже на блокировку на одном объекте и затем блокировку на другом, прежде чем освободить первый замок, например:
lock(a)
{
...
lock(b)
{
...
}
}
Нет возможности преемственности. В С# это означает, что один поток не может заставить другой поток освободить блокировку.
Условие циклического ожидания. Это означает, что существует цикл потоков, каждый из которых ждет следующего, чтобы освободить ресурс, прежде чем он сможет продолжить.
Далее он объясняет, что способ избежать взаимоблокировок состоит в том, чтобы избегать (или препятствовать) четырех условий.
Джо Даффи обсуждает несколько методовдля избежания и обнаружения взаимоблокировок, в том числе известный как блокировка. При выравнивании блокировки назначаются блокировки числовые значения и потоки должны только приобретать блокировки, которые имеют более высокие числа, чем блокировки, которые у них уже есть приобрела. Это предотвращает возможность цикла. Это также часто трудно преуспеть в типичное программное приложение сегодня, и несоблюдение уровня блокировки на каждом захвате блокировки приглашает тупиковый.
Классический сценарий тупиковой ситуации: A удерживает блокировку X и хочет получить блокировку Y, а B удерживает блокировку Y и хочет получить блокировку X. Поскольку ни один из них не может завершить то, что они пытаются сделать, оба будут в ожидании навсегда ( если не используются тайм-ауты).
В этом случае можно избежать взаимоблокировки, если A и B приобретают блокировки в том же порядке.
Обеспечение того, чтобы все транзакции влияли на таблицы в том же порядке, является ключом к предотвращению наиболее распространенных взаимоблокировок.
Например:
Транзакция A
UPDATE Table A SET Foo = 'Bar'
UPDATE Table B SET Bar = 'Foo'
Транзакция B
UPDATE Table B SET Bar = 'Foo'
UPDATE Table A SET Foo = 'Bar'
Это, скорее всего, приведет к тупиковой ситуации, когда транзакция A получает блокировку в таблице A, транзакция B получает блокировку на таблице B, поэтому ни одна из них не получает блокировка для их второй команды, пока другая не закончит.
Все другие формы взаимоблокировок, как правило, вызваны использованием высокой интенсивности и блокировкой SQL Server во внутреннем пространстве, в то время как выделенные ресурсы.
Никаких шаблонов взаимоблокировок (и 12 лет написания многопоточных торговых приложений). Но класс TimedLock очень помог в поиске тупиков, которые существуют в коде без массивной доработки.
http://www.randomtree.org/eric/techblog/archives/2004/10/multithreading_is_hard.html
в основном, (в dotnet/С#) вы выполняете поиск/замену всех своих операторов "lock (xxx)" с помощью TimedLock.Lock(xxx) "
Если обнаружен тупик (блокировка не может быть получена в течение указанного таймаута, по умолчанию - 10 секунд), тогда генерируется исключение. Моя локальная версия также немедленно регистрирует стек. Поднимите stacktrace (желательно отладочную сборку с номерами строк), и вы сразу увидите, какие блокировки были проведены в момент сбоя и какой из них он пытался получить.
В dotnet 1.1, в ситуации взаимоблокировки, как описано, так как удача будет иметь все блокированные потоки, это будет исключать одно и то же время. Таким образом, вы получите 2+ stacktraces и всю информацию, необходимую для устранения проблемы. (2.0+, возможно, изменил модель нарезки внутренне, чтобы не было этого повезло, я не уверен)
Да - возникают взаимоблокировки, когда процессы пытаются получить ресурсы в случайном порядке. Если все ваши процессы пытаются получить одни и те же ресурсы в одном и том же порядке, возможности для блокировок значительно уменьшаются, если их не устранять.
Конечно, это не всегда легко организовать...
Я рекомендую прочитать эту статью Herb Sutter. В нем объясняются причины проблем с блокировкой и выдвигает рамки в этой статье для решения этой проблемы.
Типичным сценарием являются несоответствующие планы обновления (таблицы не всегда обновляются в том же порядке). Однако это необычно, чтобы иметь тупики, когда они находятся под большим объемом обработки.
Я склонен воспринимать тупики как факт жизни, это произойдет однажды или еще, так что у меня есть DAL, готовый обработать и повторить тупиковую операцию.
Наиболее распространенный (по моим ненаучным наблюдениям) сценарий блокировки БД очень прост:
Этого можно избежать, указав предложение "FOR UPDATE" (или аналогичное, в зависимости от конкретной RDBMS), если после чтения будет следовать обновление. Таким образом, процесс получает исключительную блокировку с самого начала, что делает невозможным этот сценарий.
Условие, которое возникает, когда каждый из двух процессов ожидает, что он завершит befoure, предшествующий. В результате обе процедуры зависают. его наиболее comonelly многозадачность и clint/server.
Тупик происходит в основном, когда существует несколько зависимых замков. В потоке и в другом потоке происходит попытка блокировки мьютекса в обратном порядке. Следует обратить внимание на использование мьютекса, чтобы избежать взаимоблокировок.
Обязательно выполните операцию после отпускания замка. Если у вас несколько блокировок, таких как порядок доступа, это ABC, порядок выпуска также должен быть ABC.
В моем последнем проекте у меня возникла проблема с взаимоблокировками в базе данных SQL Server. Проблема в обнаружении причины заключалась в том, что мое программное обеспечение и стороннее программное обеспечение используют одну и ту же базу данных и работают в одних и тех же таблицах. Было очень трудно выяснить, что вызывает тупики. В итоге я написал sql-запрос, чтобы узнать, какие процессы вызывают блокировки SQL-выражений. Вы можете найти это выражение здесь: Тупики на SQL-сервере
Чтобы избежать тупика, существует алгоритм алгоритм Banker.
Это также предоставляет полезную информацию чтобы избежать тупика.