Each object in the managed heap can be used as a lock object, which is a means of synchronizing access between threads.
I thought that it just stops the thread until the contents of {} are complete.
Well, a lock it stops other threads from locking the lock until the lock is released, which is most often at the end of the lock statement (but it can also be Monitor.Wait ).
Using lock(this) dangerous because locking is complex and understands exactly which threads are blocking, which object is very important at this time, in order to avoid deadlocks; however, if you lock(this) , you are not in control of other threads, which can also (unexpectedly) block the same object. It is much safer to use the private field to lock.
As an example, if you have (in a synchronized list):
private IList<T> innerList = ... public int Count { get { lock(this) { return innerList.Count; } } }
Then it’s easy to imagine another bit of code that also has a link to this synchronized list and a lock on it, for example:
SyncList<T> list = ... lock(list) {
This is a potential dead end; it would be much better if Count did not lock(this) , but blocked a private object, i.e.
private readonly object syncLock = new object(); public int Count { get { lock(syncLock) { return innerList.Count; } } }
Now there is no risk for this problem. Another problem is that both field events and [MethodImpl] call lock(this) . Locking on Type (for static methods) is equally dangerous for the same reasons.
source share