Я думаю, вы могли неправильно понять, что lock
делает для вас. Это не не препятствует другому коду манипулировать объектом, для которого вы взяли блокировку. Он предотвращает получение длинным потоком одного объекта, в то время как другой поток удерживает блокировку.
Если вы хотите запретить одному потоку манипулировать коллекцией, пока другой поток итерирует по ней, вам нужно поместить итерационный код и код манипуляции в блоки lock
, блокируя один и тот же объект. *
Простой образец:
class LockDemo
{
private IList<string> _items;
private object _lock = new object();
public LockDemo()
{
_items = new List<string>(new[] { "one", "two", "three" });
}
public void RemoveItem(string item)
{
lock (_lock)
{
_items.Remove(item);
}
}
public void DoSomethingThatIteratesOverTheList()
{
lock (_lock)
{
foreach (var item in _items)
{
// do something with item
}
}
}
}
Обратите внимание, как весь доступ к списку (за исключением конструктора в данном случае) заключен в блоки lock
, которые все блокируются на одном и том же объекте. Также обратите внимание, что этот объект не сам список, а объект, который используется только для целей блокировки. Это показывает, что lock
не блокирует объект как таковой, но предоставляет механизм для управления тем, какие части кода могут или не могут выполняться параллельно различными потоками.