#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.
Комментариев нет:
Отправить комментарий