#c_sharp #lock
Привет. Искал инфу про потокобезопасную коллекцию и почти везде такой код: Добавление в коллекцию public void Add(int value) { lock(sync) { Add(value); } } тут sync это private object sync = new object(); Я вставил себе. public void Add(TkeyId keyId, TkeyName keyName, Tvalue value) { lock(sync) { if (this.Where(g => g.Key.Name.Equals(keyName) && g.Key.Id.Equals(keyId)).Count() > 0) return; this.Add(new UserKey(keyId, keyName), value); } } Так вот вопрос в чем прикол.Как он блокирует за счет чего. Простым языком объясните
Ответы
Ответ 1
Конструкция lock гарантирует следующее: два блока lock (p) { // тут содержимое блока } бегущие в разных потоках, никогда не будут выполнены одновременно, если объект p один и тот же.* Если один поток находится внутри lock, то другой будет ждать окончания выполнения этого блока. В этом и состоит суть блокировки. Как именно технически это реализуется, не так уж и важно. В C# lock вызывает конструкцию Monitor.Enter, а она, в свою очередь, внутри кода BCL реализует функциональность, подобную CRITICAL_SECTION самостоятельно, используя короткий холостой цикл (spin wait) и системные примитивы синхронизации. На других системах, разумеется, используются другие синхронизационные функции ОС. Как именно работают эти функции — внутренняя подробность устройства ОС (завязанная, надо думать, на системный планировщик потоков). Главное — знать, что внутрь lock'а на один и тот же объект два потока проникнуть не могут. *Также она гарантирует нужные memory barrier'ы для многопоточного сценария, но это неважно в контексте данного обсуждения.Ответ 2
Оператор lock (sync) { ... } будет транслирован в следующую конструкцию (.NET >= 4): // Флаг успешной блокировки bool acquiredLock = false; try { // Захватываем блокировку для sync Monitor.Enter(lockObject, ref acquiredLock); // Потокобезопасный код } finally { // Освобождаем блокировку для sync если блокировка была выполнена if (acquiredLock) { Monitor.Exit(lockObject); } } Когда потоком вызывается метод Monitor.Enter то участок кода будет заблокирован для доступа других потоков, вплоть до того момента, когда поток не вызовет метод Monitor.Exit.
Комментариев нет:
Отправить комментарий