欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > C#中如何实现读写分离

C#中如何实现读写分离

2025/4/2 0:12:50 来源:https://blog.csdn.net/weixin_64532720/article/details/146482032  浏览:    关键词:C#中如何实现读写分离

1. 使用 ReaderWriterLockSlim

.NET 提供的高性能读写锁,支持以下模式:

  • 读模式(Read Lock):允许多个线程同时读取。

  • 写模式(Write Lock):独占锁,其他所有读写操作都会被阻塞。

using System.Threading;public class ReadWriteExample
{private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();private int _sharedData = 0;// 读操作public int ReadData(){_lock.EnterReadLock();try{return _sharedData;}finally{_lock.ExitReadLock();}}// 写操作public void WriteData(int value){_lock.EnterWriteLock();try{_sharedData = value;}finally{_lock.ExitWriteLock();}}
}

优点

  • 细粒度控制读写操作。

  • 支持递归锁和超时机制。

缺点

  • 需要手动管理锁的获取和释放。

2. 使用 Concurrent 并发集合

.NET 的 System.Collections.Concurrent 命名空间提供了线程安全的集合类,内部已实现读写分离逻辑:

  • ConcurrentDictionary<TKey, TValue>

  • ConcurrentQueue<T>

  • ConcurrentBag<T>

using System.Collections.Concurrent;public class ConcurrentExample
{private readonly ConcurrentDictionary<string, int> _data = new();// 读操作(无锁)public int GetValue(string key){return _data.TryGetValue(key, out int value) ? value : -1;}// 写操作(内部使用细粒度锁)public void UpdateValue(string key, int value){_data.AddOrUpdate(key, value, (k, oldValue) => value);}
}

优点

  • 开箱即用,无需手动管理锁。

  • 高性能,适合高频读写场景。

缺点

  • 灵活性较低,仅适用于预定义的集合类型。

3. 基于 volatile 和内存屏障(Memory Barrier)

适用于简单变量的读写分离,通过 volatile 关键字确保内存可见性:

public class VolatileExample
{private volatile bool _flag = false;private int _data = 0;// 读操作(无锁)public int ReadData(){if (_flag)return _data;return -1;}// 写操作(需要同步)public void WriteData(int value){Interlocked.Exchange(ref _data, value); // 原子写入Volatile.Write(ref _flag, true);        // 确保写入对其他线程可见}
}

优点

  • 轻量级,适合简单场景。

  • 无锁读操作。

缺点

  • 仅适用于简单类型(如 intbool)。

  • 需要手动处理内存可见性。

4. 数据库读写分离

在数据库层面实现读写分离(如主从架构),C# 代码通过不同连接字符串路由请求:

public class DatabaseRouter
{private static readonly string ReadConnectionString = "Server=ReadServer;...";private static readonly string WriteConnectionString = "Server=WriteServer;...";public IDbConnection GetReadConnection() => new SqlConnection(ReadConnectionString);public IDbConnection GetWriteConnection() => new SqlConnection(WriteConnectionString);
}// 使用示例
using (var readConn = DatabaseRouter.GetReadConnection())
{// 执行查询操作
}using (var writeConn = DatabaseRouter.GetWriteConnection())
{// 执行更新操作
}

优点

  • 直接利用数据库主从复制特性。

  • 减轻主库压力。

缺点

  • 需要数据库支持主从同步。

  • 可能存在数据同步延迟。

5. 基于不可变数据(Immutable Data)

通过每次修改生成新对象实现无锁读取(如使用 ImmutableList<T> 或自定义不可变类型):

using System.Collections.Immutable;public class ImmutableExample
{private ImmutableList<int> _data = ImmutableList<int>.Empty;// 读操作(无锁)public int GetItem(int index){return _data[index];}// 写操作(原子替换)public void AddItem(int item){ImmutableInterlocked.Update(ref _data, list => list.Add(item));}
}

优点

  • 完全无锁读取。

  • 天然线程安全。

缺点

  • 频繁修改可能产生内存压力。

选择策略

场景推荐方案
细粒度代码级读写控制ReaderWriterLockSlim
高频并发集合操作ConcurrentDictionary 等并发集合
简单变量的读写volatile + Interlocked
数据库访问分离主从架构 + 连接路由
高频读、低频写不可变数据(如 ImmutableList

注意事项

  1. 避免死锁确保锁的获取和释放成对出现(用 try-finally 块)。

  2. 性能权衡:读写锁适合读多写少场景,写频繁时可能不如普通锁高效。

  3. 数据一致性:数据库读写分离时需处理主从同步延迟问题。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词