Почему блокировка на коллекции.SyncRoot вместо того, чтобы просто заблокировать коллекцию?

Я пытаюсь понять точку syncroot в ICollection. Почему бы просто не запереть коллекцию?

lock(myCollection)
{
    //do stuff to myCollection
}

vs

lock(myCollection.SyncRoot)
{
    //do stuff to myCollection
}

2 ответов


Как правило, если безопасность потоков является серьезной проблемой, я бы избегал любого из этих вариантов.

для этого, как правило, для поддержания вашего собственный переменная и заблокировать его во всех методах, где это необходимо, включая весь открытый API, который обращается к коллекции.

реальная опасность заключается в том, что, заблокировав тип, который подвергается или может быть подвержен внешнему миру, вы потенциально открываете способность к " внешнему миру" чтобы испортить синхронизацию. Если используется более одного замка, это может привести к мертвым замкам (если внешние замки на что-то вы не ожидаете).

создавая закрытую переменную и блокируя исключительно ее, вы "берете под контроль" ситуацию. Это значительно проясняет происходящее. Кроме того, это облегчает синхронизацию между несколькими объектами, особенно позже, когда вы поддерживаете код, так как блокировка очень ясна.


никогда не блокируйте SyncRoot, потому что я считаю, что он делает блокировку(это), которая блокирует всю коллекцию. Если вы собираетесь заблокировать, вы должны создать объект и заблокировать его. Например

public class MyClass
{
   get {return lock(_lockObject) _myCollection ; }
   set {lock(_lockObject) _myCollection.Add(value); }


   private List<string> _myCollection = new List<string>();
   private object _lockObject = new object();
}

лучше уточнить, блокировка (myCollection.SyncRoot) и lock(myCollection) делают то же самое.
Потому что свойство SyncRoot выглядит примерно так

get { return this;}