Thread Synchronization in .NET
This comes after my last post Multi-threading in .NET. There are several synchronization mechanisms you can use in your .NET applications, so choosing among them must be done wisely.
First you must decide one thing:
Do you need to synchronize threads in different processes on the same machine?
If so, the available possibilities are:
System.Threading.Semaphore: the number of concurrent entries is specified at construction time; all entries are treated equally; the name of the synchronization object must also be specified when the semaphore is created;
System.Threading.Mutex: equals a semaphore with the maximum number of concurrent entries set to 1; the name of the synchronization object must be specified when the mutex is created;
System.Threading.EventWaitHandle (or their better known children, System.Threading.ManualResetEvent and System.Threading.AutoResetEvent): the name of the synchronization object must be specified when the instance is created, as well as the reset policy; if set to auto, whenever the EventWaitHandle is signaled, only one object waiting on it will succeed.
If you only want to synchronize threads inside a single process, you have more options, but first you must decide on this:
Do you want all of your threads to be equally treated?
If so, try these:
All of the above classes, but you can skip setting the name of the synchronization object;
System.Threading.Monitor (best known as the lock keyword): only one object at a time can have hold of the synchronization lock;
System.Runtime.CompilerServices.MethodImplAttribute attribute: if used with System.Runtime.CompilerServices.MethodImplOptions.Synchronized option, marks a method as synchronized, so there can be only one thread at a time running it.
Otherwise, the BCL has support for a classical synchronization scenario: reader-writer. In this case, all access are not equal: some require write access and some require read access. There are two classes available for implementing this:
System.Threading.ReaderWriterLock: allows at any time either: 1) a single writer or 2) any number of readers;
System.Threading.ReaderWriterLockSlim: a more recent and optimized version of ReaderWriterLock; you should use this instead.
It is worth noting that typically scenarios with different access levels offer better performance than the ones where every thread is treated the same, and thus waits on the same object.