замок внутренний замок
Мне интересно, если эта конструкция вызовет ошибку:
lock(sync)
{
// something
lock(sync)
{
//something
lock(sync)
{
//something
}
}
}
Я запустил этот код, и это кажется прекрасным, но, может быть, в некоторых обстоятельствах может возникнуть ошибка?
3 ответа:
lock
- Это оболочка дляMonitor.Enter
иMonitor.Exit
:The
lock
ключевое слово называетEnter
в начале блока иExit
в конце блока. Из документации первого:из документации
Monitor.Enter
:это законно для того же потока, чтобы вызвать
Enter
более одного раза без его блокировки; однако, равное количествоExit
вызовы должны быть вызывается до того, как другие потоки, ожидающие объекта, разблокируются.потому что звонки
Enter
иExit
сопряжены, ваш шаблон кода имеет четко определенное поведение.обратите внимание, однако, что
lock
не гарантируется, что это конструкция без исключений:A
ThreadInterruptedException
бросается, еслиInterrupt
прерывает поток, ожидающий вводаlock
заявление.
чтобы объяснить, почему это четко определенное поведение и никогда не подведет:
в сторону: этот ответ имеет более подробную информацию о том, как замки на самом деле работают
блокировка происходит при
Thread
уровень, поэтому вызов его во второй раз в том же потоке будет избыточным. Я бы подумал, что это не будет иметь никакого штрафа за производительность (хотя это будет зависеть от того, как именно написаны внутренности .Net, поэтому я не могу этого гарантировать)много раз ты у вас есть публичная функция, которая вызывает другую публичную функцию в вашем классе, которой нужна блокировка при использовании отдельно. Если бы это не было разрешено, следующее не удалось бы:
private Dictionary<string, int> database = new Dictionary<string, int>(); private object databaseLock = new object(); public void AddOrUpdate(string item) { lock (databaseLock) { if (Exists(item)) database.Add(item, 1); else ++database[item]; } } public bool Exists(string item) { lock (databaseLock) { //... Maybe some pre-processing of the key or item... return database.ContainsKey(item); } }