замок внутренний замок
Мне интересно, если эта конструкция вызовет ошибку:
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); } }