Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between `Synclock syncroot` and `SyncLock Me`?

vb.Net multithreading question:

What is the difference between

SyncLock syncRoot  
  ''# Do Stuff  
End SyncLock

-and-

SyncLock Me  
  ''# Do Stuff  
End SyncLock
like image 329
Vivian River Avatar asked May 18 '10 15:05

Vivian River


1 Answers

All code that happens within a SyncLock block is synchronized with all other code happening within a SyncLock block on the same object. Obviously, Me is not the same as syncRoot (which is, I'm assuming, Me.SyncRoot, if your Me is an ICollection).

Code happening within a SyncLock block on one object is not going to be synchronized with code within a SyncLock block on a different object.

Say you have this code:

' happening on thread 1 '
SyncLock myColl.SyncRoot
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl.SyncRoot
    myColl.Remove(myObject)
End SyncLock

The above is fine: the Add and Remove calls are synchronized, meaning they will not occur simultaneously (whichever gets called first will execute, and the second will not execute until the first is finished).

But suppose you had this instead:

' happening on thread 1 '
SyncLock myColl.SyncRoot
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl ' NOTE: SyncLock on a different object '
    myColl.Remove(myObject)
End SyncLock

The above Add and Remove calls are not synchronized in any way, shape, or form. Thus there is no thread safety in the above code.

Now, why does SyncRoot exist? Quite simply, because it makes sense to synchronize on the smallest scale necessary; i.e., there is no need to synchronize code that doesn't actually need to be synchronized.

Consider this example:

' happening on thread 1 '
SyncLock myColl
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl
    ' Why you would have code like this, I do not know; '
    ' this is just for illustration. '
    myColl.Name = myColl.Name.Replace("Joe", "Bill")
End SyncLock

' happening on thread 3 '
SyncLock myColl
    myColl.Name = myColl.Name.Replace("Bill", "Joe")
End SyncLock

In the above, you are synchronizing more than necessary. The Add call really has nothing to do with the renaming of the myColl object; thus the code does not need to be synchronized.

This is the idea behind the SyncRoot property: it gives you an object whose entire purpose is to provide a common object with which modifications to/enumerations of the collection can be synchronized. Code that involves the collection in some other way -- but which does not need to be synchronized with code that modifies or reads the contents of the collection -- should be synchronized, where appropriate, on a different object.

like image 78
Dan Tao Avatar answered Oct 12 '22 07:10

Dan Tao