Страницы

Поиск по вопросам

четверг, 4 апреля 2019 г.

Потокобезопасная коллекция с#

Привет. Искал инфу про потокобезопасную коллекцию и почти везде такой код:
Добавление в коллекцию
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); } }
Так вот вопрос в чем прикол.Как он блокирует за счет чего. Простым языком объясните


Ответ

Конструкция lock гарантирует следующее: два блока
lock (p) { // тут содержимое блока }
бегущие в разных потоках, никогда не будут выполнены одновременно, если объект p один и тот же.* Если один поток находится внутри lock, то другой будет ждать окончания выполнения этого блока. В этом и состоит суть блокировки.
Как именно технически это реализуется, не так уж и важно. В C# lock вызывает конструкцию Monitor.Enter, а она, в свою очередь, внутри кода BCL реализует функциональность, подобную CRITICAL_SECTION самостоятельно, используя короткий холостой цикл (spin wait) и системные примитивы синхронизации. На других системах, разумеется, используются другие синхронизационные функции ОС. Как именно работают эти функции — внутренняя подробность устройства ОС (завязанная, надо думать, на системный планировщик потоков).
Главное — знать, что внутрь lock'а на один и тот же объект два потока проникнуть не могут.

*Также она гарантирует нужные memory barrier'ы для многопоточного сценария, но это неважно в контексте данного обсуждения.

Комментариев нет:

Отправить комментарий