- Monitor:
- 定义:
Monitor
是 C# 中最基本的同步机制,通过Enter
和Exit
方法来控制对共享资源的访问。它提供了排他锁的功能,确保在任何时刻只有一个线程可以访问共享资源。 - 优点:简单易用,适合对临界区进行粗粒度的同步控制。
- 缺点:只能实现排它锁,不能实现读写锁,性能相对较低。
- 定义:
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(); } Console.ReadKey(); } static void IncrementCounter() { Monitor.Enter(_lock); try { _counter++; Console.WriteLine($"Counter: {_counter}"); } finally { Monitor.Exit(_lock); } } }
- Mutex:
- 定义:
Mutex
是一个操作系统对象,用于在进程间共享,通过WaitOne
和ReleaseMutex
来控制对共享资源的访问。它提供了进程间的同步能力。 - 优点:可跨进程使用,适合在进程间进行同步。
- 缺点:相比
Monitor
,性能开销较大,因为涉及到系统调用。
- 定义:
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(); } Console.ReadKey(); } static void IncrementCounter() { _mutex.WaitOne(); _counter++; Console.WriteLine($"Counter: {_counter}"); _mutex.ReleaseMutex(); } }
- ReaderWriterLockSlim:
- 定义:
ReaderWriterLockSlim
实现了读写分离锁,允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。这种机制适用于读多写少的场景。 - 优点:适合读多写少的场景,提高了并发性能。
- 缺点:相对复杂,可能会引起死锁,不支持递归锁。
- 定义:
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(); } Console.ReadKey(); } static void ReadCounter() { _rwLock.EnterReadLock(); Console.WriteLine($"Counter: {_counter}"); _rwLock.ExitReadLock(); } static void IncrementCounter() { _rwLock.EnterWriteLock(); _counter++; Console.WriteLine($"Counter incremented to: {_counter}"); _rwLock.ExitWriteLock(); } }
- Semaphore:
- 定义:
Semaphore
是一个信号量,用于控制同时访问共享资源的线程数量。通过WaitOne
和Release
方法,可以控制访问资源的线程数量。 - 优点:可以控制多个线程同时访问共享资源的数量,灵活性较高。
- 缺点:相对于其他机制,使用起来较为复杂,需要谨慎处理信号量的释放。
- 定义:
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(); } Console.ReadKey(); } static void IncrementCounter() { _semaphore.WaitOne(); _counter++; Console.WriteLine($"Counter: {_counter}"); _semaphore.Release(); } }
- SemaphoreSlim:
- 定义:
SemaphoreSlim
是轻量级的信号量,与Semaphore
类似,用于控制同时访问共享资源的线程数量,但相比Semaphore
更轻量级。 - 优点:相比
Semaphore
,SemaphoreSlim
的开销更小,适用于资源访问频繁的场景。 - 缺点:与
Semaphore
相比,功能上略有限制,例如没有Release(Int32)
方法,只能递增信号量一个单位。
- 定义:
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(); } Console.ReadKey(); } static void IncrementCounter() { _semaphore.Wait(); _counter++; Console.WriteLine($"Counter: {_counter}"); _semaphore.Release(); } }
- lock:
- 定义:
lock
关键字用于在代码块级别实现互斥锁,确保共享资源在多线程环境中被安全访问。lock
关键字确保在同一时间只有一个线程可以访问共享资源,从而避免竞态条件和数据损坏。此外,
lock
关键字在 C# 中是基于 Monitor 的概念实现的。lock
关键字在 C# 中是基于 Monitor 的概念实现的语法糖。当使用lock
关键字时,它会自动获取对象的监视器锁(Monitor),并在代码块执行完毕后释放这个锁,以确保线程安全性。 - 优点:
- 简单易用:
lock
提供了一种简单的方式来实现线程同步,避免了开发人员手动管理锁的复杂性。 - 自动释放:
lock
会自动释放锁,避免了忘记释放锁导致死锁的情况。 - 确保线程安全:通过使用
lock
,可以确保共享资源在多线程环境下的安全访问。
- 简单易用:
- 缺点:
- 潜在死锁:如果在锁内部发生了阻塞操作,可能会导致死锁情况的发生。
- 性能开销:频繁使用
lock
可能会导致性能开销,因为其他线程需要等待锁的释放。 - 可能引发竞态条件:如果
lock
的粒度过大,可能会导致竞态条件的发生,影响程序性能。
- 定义:
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(); } Console.ReadKey(); } static void IncrementCounter() { lock (_lock) { _counter++; Console.WriteLine($"Counter: {_counter}"); } } }