- Monitor:
- Definition:
Monitor
is the most basic synchronization mechanism in C#, and is implemented via theEnter
cap (a poem)Exit
method to control access to shared resources. It provides exclusive locking to ensure that only one thread can access the shared resource at any given moment. - Advantages: easy to use, suitable for coarse-grained synchronization control of critical zones.
- Disadvantages: can only realize the exclusion lock, can not realize the read-write lock, performance is relatively low.
- Definition:
class Program { static readonly object _lock = new object(); static int _counter = 0; static void Main() { for (int i = 0; i < 10; i++) { new Thread(IncrementCounter).Start(); } (); } static void IncrementCounter() { lock (_lock) { _counter++; ($"Counter: {_counter}"); } } }
- Mutex:
- Definition:
Mutex
is an operating system object that is used to be shared between processes via theWaitOne
respond in singingReleaseMutex
to control access to shared resources. It provides the ability to synchronize between processes. - Pros: can be used across processes, suitable for synchronization between processes.
- Cons: Compared to
Monitor
, the performance overhead is higher because of the system calls involved.
- Definition:
class Program { static Mutex _mutex = new Mutex(); static int _counter = 0; static void Main() { for (int i = 0; i < 10; i++) { new Thread(IncrementCounter).Start(); } (); } static void IncrementCounter() { _mutex.WaitOne(); _counter++; ($"Counter: {_counter}"); _mutex.ReleaseMutex(); } }
- ReaderWriterLockSlim:
- Definition:
ReaderWriterLockSlim
A read-write separation lock is implemented to allow multiple threads to read the shared resource at the same time, but only one thread is allowed to write to the shared resource. This mechanism is suitable for scenarios with many reads and few writes. - Pros: suitable for scenarios with many reads and few writes, improves concurrency performance.
- Cons: relatively complex, may cause deadlocks, does not support recursive locks.
- Definition:
class Program { static ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(); static int _counter = 0; static void Main() { for (int i = 0; i < 5; i++) { new Thread(ReadCounter).Start(); new Thread(IncrementCounter).Start(); } (); } static void ReadCounter() { _rwLock.EnterReadLock(); ($"Counter: {_counter}"); _rwLock.ExitReadLock(); } static void IncrementCounter() { _rwLock.EnterWriteLock(); _counter++; ($"Counter incremented to: {_counter}"); _rwLock.ExitWriteLock(); } }
- Semaphore:
- Definition:
Semaphore
is a semaphore used to control the number of threads accessing a shared resource at the same time. The number of threads accessing a shared resource at the same time is controlled by theWaitOne
cap (a poem)Release
method, you can control the number of threads accessing the resource. - Pros: you can control the number of multiple threads accessing shared resources at the same time, higher flexibility.
- Cons: More complex to use compared to other mechanisms, requires careful handling of semaphore releases.
- Definition:
class Program { static Semaphore _semaphore = new Semaphore(2, 2); // Allow 2 threads to access the resource simultaneously static int _counter = 0; static void Main() { for (int i = 0; i < 5; i++) { new Thread(IncrementCounter).Start(); } (); } static void IncrementCounter() { _semaphore.WaitOne(); _counter++; ($"Counter: {_counter}"); _semaphore.Release(); } }
- SemaphoreSlim:
- Definition:
SemaphoreSlim
is a lightweight semaphore, similar to theSemaphore
Similarly, it is used to control the number of threads accessing a shared resource at the same time, but compared to theSemaphore
Lighter. - Pros: Compared to
Semaphore
,SemaphoreSlim
has less overhead and is suitable for scenarios with frequent resource access. - Disadvantages: with
Semaphore
Compared to this, the functionality is slightly limited, e.g. there is noRelease(Int32)
method, which can only increment the semaphore by one unit.
- Definition:
class Program { static SemaphoreSlim _semaphore = new SemaphoreSlim(2, 2); // Allow 2 threads to access the resource simultaneously static int _counter = 0; static void Main() { for (int i = 0; i < 5; i++) { new Thread(IncrementCounter).Start(); } (); } static void IncrementCounter() { _semaphore.Wait(); _counter++; ($"Counter: {_counter}"); _semaphore.Release(); } }
- lock:
- Definition:
lock
is a keyword in C# used to implement mutex locks at the block level to protect shared resources from being accessed by multiple threads at the same time. - Advantages: easy to use, suitable for fine-grained synchronization control of critical zones, easier to write.
- Disadvantages: can only be used for synchronization within a single thread, not across threads or processes, and can lead to deadlocks if not used carefully.
- Definition:
class Program { static readonly object _lock = new object(); static int _counter = 0; static void Main() { for (int i = 0; i < 5; i++) { new Thread(IncrementCounter).Start(); } (); } static void IncrementCounter() { lock (_lock) { _counter++; ($"Counter: {_counter}"); } } }