Why lock on Collection.SyncRoot instead of just lo

2019-01-25 14:02发布

问题:

I'm trying to understand the point of the syncroot in ICollection. Why not just lock the collection?

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

vs

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

回答1:

Typically, if thread safety is a serious concern, I would avoid either of these options.

A far better option is typically to maintain your own private variable, and lock on it in all methods where it's required - including the entire public API that accesses the collection.

The real danger is that, by locking on a type that's exposed or could be exposed to the outside world, you potentially open up the ability for the "outside world" to mess with your synchronization. If more than one lock is being used, this can lead to dead locks (if the outside locks on something you aren't expecting).

By creating a private variable, and locking exclusively on it, you're "taking control" of the situation. This makes it much more clear what is occurring. In addition, it eases synchronization between multiple objects, especially later as you maintain the code, since the lock is very clear.



回答2:

Never lock on SyncRoot because I believe it does a lock(this) which is locking on the entire collection. If you're going to lock, you should create an object and lock on it. For example

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();
}

To better clarify, lock(myCollection.SyncRoot) and lock(myCollection) do the same thing.
Because the property SyncRoot looks something like this

get { return this; }