编辑
2025-10-11
C#
00

目录

ReaderWriterLockSlim 的特点
使用 ReaderWriterLockSlim 的基本语法
3示例:使用 ReaderWriterLockSlim 实现线程安全的字典
代码解析
4. 示例:使用 ReaderWriterLockSlim 的升级操作
代码解析
使用 ReaderWriterLockSlim 的注意事项
结论

ReaderWriterLockSlim 是 .NET Framework 中用于管理对共享资源的访问的一种同步机制。与传统的锁机制(如 MonitorMutex)相比,ReaderWriterLockSlim 更加高效,特别是在读操作远多于写操作的场景中。本文将详细介绍 ReaderWriterLockSlim 的特点、用法,以及多个示例以展示其应用。

ReaderWriterLockSlim 的特点

  • 读写分离:允许多个线程同时读取共享资源,但在写入时会独占访问。因此,它特别适合读多写少的场景。
  • 高效性:在读操作频繁的情况下,性能显著优于传统的锁,因为多个读线程可以并行执行。
  • 加锁机制:提供独占锁(用于写操作)、共享锁(用于读操作)机制,并支持升级锁定。
  • 优雅的管理:提供 EnterReadLockEnterWriteLockExitReadLockExitWriteLock 方法来控制访问。

使用 ReaderWriterLockSlim 的基本语法

以下是 ReaderWriterLockSlim 的基本用法示例:

C#
using System.Threading; ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(); // 读操作 rwLock.EnterReadLock(); // 读取共享资源 rwLock.ExitReadLock(); // 写操作 rwLock.EnterWriteLock(); // 写入共享资源 rwLock.ExitWriteLock();

3示例:使用 ReaderWriterLockSlim 实现线程安全的字典

以下示例展示了如何使用 ReaderWriterLockSlim 来实现一个线程安全的字典,支持多个线程同时读取,但是在写入时会进行独占访问。

C#
namespace AppReaderWriterLockSlim { internal class Program { private static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(); private static Dictionary<int, string> data = new Dictionary<int, string>(); static void Main(string[] args) { Thread[] writers = new Thread[3]; Thread[] readers = new Thread[5]; for (int i = 0; i < writers.Length; i++) { writers[i] = new Thread(Writer); writers[i].Start(i + 1); } for (int i = 0; i < readers.Length; i++) { readers[i] = new Thread(Reader); readers[i].Start(i + 1); } foreach (var writer in writers) { writer.Join(); } foreach (var reader in readers) { reader.Join(); } } static void Writer(object id) { for (int i = 0; i < 5; i++) { rwLock.EnterWriteLock(); try { int key = i + (int)id * 10; // 确保写入不同的键 data[key] = $"Writer {id} wrote {key}"; Console.WriteLine($"Writer {id} added key {key}"); } finally { rwLock.ExitWriteLock(); } Thread.Sleep(100); // 模拟延迟 } } static void Reader(object id) { for (int i = 0; i < 5; i++) { rwLock.EnterReadLock(); try { foreach (var kvp in data) { Console.WriteLine($"Reader {id} read: {kvp.Key} => {kvp.Value}"); } } finally { rwLock.ExitReadLock(); } Thread.Sleep(50); // 模拟延迟 } } } }

image.png

代码解析

  1. 共享资源:使用 Dictionary<int, string> 作为共享资源 data
  2. 读写锁实例ReaderWriterLockSlim 实例 rwLock 用于控制对 data 的并发访问。
  3. 写线程:每个 Writer 线程通过 EnterWriteLock 进入写模式,写入数据并使用 ExitWriteLock 释放锁。
  4. 读线程:每个 Reader 线程通过 EnterReadLock 进入读模式,同时读取资源,多个读线程可以同时执行。
  5. 线程管理:主线程启动所有写入和读取线程,并等待它们结束。

4. 示例:使用 ReaderWriterLockSlim 的升级操作

在某些场景中,可能会需要从读锁升级到写锁。以下示例演示了如何处理这种情况。

C#
namespace AppReaderWriterLockSlim { internal class Program { private static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(); private static List<string> data = new List<string>(); static void Main(string[] args) { // 启动写入线程 Thread writer = new Thread(WriteData); writer.Start(); // 启动读取线程 Thread reader = new Thread(ReadAndUpdate); reader.Start(); writer.Join(); reader.Join(); } static void WriteData() { rwLock.EnterWriteLock(); try { for (int i = 0; i < 5; i++) { data.Add($"Item {i}"); Console.WriteLine($"写入: Item {i}"); Thread.Sleep(100); } } finally { rwLock.ExitWriteLock(); } } static void ReadAndUpdate() { for (int i = 0; i < 3; i++) { rwLock.EnterReadLock(); try { Console.WriteLine("读取数据:"); foreach (var item in data) { Console.WriteLine(item); } } finally { rwLock.ExitReadLock(); } // 试图升级到写锁(通常不建议这样做,因可能引起死锁) rwLock.EnterWriteLock(); try { // 更新数据的示例 if (data.Count > 0) { data[0] = "Updated Item"; Console.WriteLine("更新数据: Updated Item"); } } finally { rwLock.ExitWriteLock(); } Thread.Sleep(200); } } } }

image.png

代码解析

  1. 数据列表:使用 List<string> 作为共享资源,以模拟多个操作。
  2. 写入线程WriteData() 方法中写入数据,使用 EnterWriteLockExitWriteLock 来控制访问。
  3. 读取与更新线程ReadAndUpdate() 方法中首先读取数据,然后在持有读锁的情况下升级到写锁进行数据更新(注意:在实际应用中不推荐通读锁升级到写锁,以避免死锁的风险)。
  4. 延迟模拟:使用 Thread.Sleep() 模拟操作延迟,增加程序的可观测性。

使用 ReaderWriterLockSlim 的注意事项

  • 避免死锁:在进行锁的请求时,确保遵循一定的顺序及逻辑,防止死锁的发生。
  • 性能考虑:虽然 ReaderWriterLockSlim 在读多写少的场景下表现良好,但在写操作频繁的情况下可能会导致性能下降。
  • 释放锁:确保在每次使用后都释放锁,特别是在发生异常时,避免造成资源的长期占用。
  • 避免锁的升级:尽量避免从读锁直接升级到写锁,这样的操作可能导致死锁或不可预知的线程行为。

结论

ReaderWriterLockSlim 是C#中一种强大且高效的锁机制,特别适合读多写少的场景。通过上述示例,您可以看到如何利用 ReaderWriterLockSlim 来实现线程安全的操作,并提高应用程序的并发性能。合理地使用 ReaderWriterLockSlim 有助于提升程序的可靠性和效率。在应用中,开发者应关注性能优化、避免死锁及异常处理,以确保高效的多线程操作。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!