Приведет ли следующий код к тупиковой ситуации при использовании C # в .NET?
class MyClass
{
private object lockObj = new object();
public void Foo()
{
lock(lockObj)
{
Bar();
}
}
public void Bar()
{
lock(lockObj)
{
// Do something
}
}
}
Ответы:
Нет, пока вы блокируете один и тот же объект. Рекурсивный код фактически уже имеет блокировку и поэтому может беспрепятственно продолжать работу.
lock(object) {...}
- это сокращение от использования класса Monitor . Как указывает Марк ,Monitor
позволяет повторный вход , поэтому повторные попытки заблокировать объект, на котором текущий поток уже имеет блокировку, будут работать нормально.Если вы начинаете блокировать разные объекты, тогда вам нужно быть осторожным. Обратите особое внимание на:
Если вы нарушите любое из этих правил, в какой-то момент у вас наверняка возникнут проблемы с тупиком .
Вот одна хорошая веб-страница, описывающая синхронизацию потоков в .NET: http://dotnetdebug.net/2005/07/20/monitor-class-avoiding-deadlocks/
Кроме того, фиксируйте одновременно как можно меньше объектов. По возможности подумайте о применении крупнозернистых замков . Идея состоит в том, что если вы можете написать свой код таким образом, чтобы существовал граф объектов, и вы можете получить блокировки в корне этого графа объектов, то сделайте это. Это означает, что у вас есть одна блокировка для этого корневого объекта, и поэтому вам не нужно так сильно беспокоиться о последовательности, в которой вы устанавливаете / снимаете блокировки.
(Еще одно замечание: ваш пример технически не рекурсивен. Чтобы он был рекурсивным,
Bar()
он должен вызывать сам себя, как правило, как часть итерации.)источник
Ну,
Monitor
позволяет повторный вход, поэтому вы не можете заблокировать себя ... так что нет: этого не должно бытьисточник
Если поток уже удерживает блокировку, он не будет блокировать себя. Инфраструктура .Net обеспечивает это. Вам нужно только убедиться, что два потока не пытаются получить одни и те же две блокировки вне очереди с помощью любых путей кода.
Один и тот же поток может получать одну и ту же блокировку несколько раз, но вы должны убедиться, что вы снимаете блокировку столько же раз, сколько вы ее получаете. Конечно, если для этого используется ключевое слово «lock», это происходит автоматически.
источник
Нет, в этом коде не будет мертвых замков. Если вы действительно хотите создать тупик, для простейшего потребуется минимум 2 ресурса. Рассмотрим сценарий «собака и кость». 1. Собака полностью контролирует одну кость, поэтому любой другой собаке придется ждать. 2. Две собаки с двумя костями необходимы как минимум для создания тупика, когда они, соответственно, блокируют свои кости и ищут также и другие кости.
.. и так далее, n собак и m костей и вызывают более сложные тупики.
источник