如果我们只是简单的使用lock方式去加锁,则会影响性能。如果采用读写锁,那么多个线程可以同时读取该对象,只有等到对象被写入锁占用的时候,才会阻塞。 也就是说某个线程进入了写入模式,那么其他线程无论是要写入还是读取,都是会被阻塞的。
ReaderWriterLockSlim可以将读锁和写锁进行分离,读锁允许多线程读取数据,写锁在被释放前会阻塞了其他线程的所有操作。 下面以一个读Dictionary数据作为示例 static ReaderWriterLockSlim _rw = new ReaderWriterLockSlim(); static
1、简介 .NET 3.5 开始 ReaderWriterLockSlim登上舞台,ReaderWriterLockSlim 可以看做是 ReaderWriterLock 的升级版。 由于 ReaderWriterLockSlim 默认不支持递归调用、所以在某种意义上来说更不容易造成死锁。 ReaderWriterLockSlim 类支持三种锁定模式:Read,Write,UpgradeableRead。 4、通过默认构造函数创建的读写锁是不支持递归的,若想支持递归 可通过构造 ReaderWriterLockSlim(LockRecursionPolicy) 创建实例。 的介绍,能大致得知道ReaderWriterLockSlim得用处,在多线程并发操作共享资源时,很有用处. 2、通过ReaderWriterLockSlim封装一个同步缓存实例 下面时MS提供的封装,我做了略微的修改
阅读目录 volatile Interlocked ReaderWriterLockSlim volatile 简单来说volatile关键字是告诉c#编译器和JIT编译器,不对volatile标记的字段做任何的缓存 答案就是我们的ReaderWriterLockSlim主角,读写锁。 ReaderWriterLockSlim 其中一种锁EnterUpgradeableReadLock最关键 即可升级锁。 推荐使用升级版的 ReaderWriterLockSlim 。 //实例一个读写锁 ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion public class SynchronizedCache { private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim
FlowEngine> flowEngines = new Dictionary<int, FlowEngine>();
// 读写锁
private static ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim();
///
目录 ReaderWriterLockSlim ReaderWriterLockSlim 常用方法 订单系统示例 并发字典写示例 ReaderWriterLock 本篇的内容主要是介绍 ReaderWriterLockSlim ReaderWriterLockSlim 老规矩,先大概了解一下 ReaderWriterLockSlim 常用的方法。 ReaderWriterLockSlim 的读、写入锁模板如下: private static ReaderWriterLockSlim toolLock = new ReaderWriterLockSlim ReaderWriterLockSlim tool = new ReaderWriterLockSlim(); // 读写锁 private static int MaxId = 增加两个静态变量: private static ReaderWriterLockSlim toolLock = new ReaderWriterLockSlim();
到这个时候,我们就要想到读写锁ReaderWriterLockSlim。 宝藏好物:ReaderWriterLockSlim Use ReaderWriterLockSlim to protect a resource that is read by multiple threads 简而言之: ReaderWriterLockSlim提供对某资源在某时刻下的多线程同读 或 单线程独占写。 此外,ReaderWriterLockSlim还提供从读模式无缝升级到独占写模式。 微软ReaderWriterLockSlim页面还很贴心的给了一个基于读写锁的缓存操作封装类SynchronizedCache 开箱即用的缓存操作类 基于ReaderWriterLockSlim对线程不安全的 public class SynchronizedCache { private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim
接下来看一下ReaderWriterLockSlim类:
///
用ReaderWriterLockSlim化解锁竞争 某次事故中,多线程频繁争抢锁导致应用响应迟缓。问题源于一个被过度锁定的共享配置字典。 传统锁的弊端:lock语句阻塞并发读操作。 解决方案:ReaderWriterLockSlim允许多线程并发读,写操作独占访问。 private readonly ReaderWriterLockSlim _lock = new(); private Dictionary<string, string> _config = new • 内存敏感场景:拥抱Span<T>和Memory<T> • 高并发读写:用ReaderWriterLockSlim替代传统锁 • 异步上下文:AsyncLocal<T>让链路跟踪无忧 • 集合操作:ToHashSet
在System.Core中ReaderWriterLockSlim类比较好用,它是基于写优先策略的。它还支持从读锁升级到写锁,称为Upgradable Mode. 简单测试代码如下: private static void Test() { ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
用ReaderWriterLockSlim缓解锁竞争 某次生产事故中,过度使用的lock关键字导致线程频繁阻塞,应用响应如龟爬。罪魁祸首是一个被高频读写的共享配置字典。 解决方案是ReaderWriterLockSlim:允许多线程并发读,写操作独占访问。 private readonly ReaderWriterLockSlim _lock = new(); private Dictionary<string, string> _config = new 关键点:高并发读场景下,ReaderWriterLockSlim是锁优化的银弹。 3. 普通开发者与资深工程师的差距,往往在于知道优化什么与何时优化: • 大数据处理 → Span/Memory • 高并发锁竞争 → ReaderWriterLockSlim • 异步上下文跟踪 → AsyncLocal
下面我们接着讲线程同步相关的知识点,本节主要讲解以下四小节的内容: CountDownEvent Barrier ReaderWriterLockSlim SpinWait 零、CountDownEvent 二、ReaderWriterLockSlim ReaderWriterLockSlim 类会创建线程安全机制,它允许多个线程读取的同时只有一个线程独占资源。 我们一般使用 ReaderWriterLockSlim 来保护由多个线程读取但每次只采用一个线程写入的资源。 ReaderWriterLockSlim 允许多个线程均处于读取模式,允许一个线程处于写入模式并独占锁定状态,同时还允许一个具有读取权限的线程处于可升级的读取模式,在此模式下线程无需放弃对资源的读取权限即可升级为写入模式 lockSlim = new ReaderWriterLockSlim(); static List<int> items = new List<int>(); static
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();public void ReadData(){ _lock.EnterReadLock 4.4 避免死锁避免嵌套锁,使用try-finally块,并考虑使用Semaphore或ReaderWriterLockSlim。
C#中包含了一个读写锁ReaderWriterLockSlim,专门用来解决读者写者问题的。因此这里就直接使用这个类来实现。 /summary> /// <typeparam name="T"></typeparam> public class Reader<T> where T : IData { private ReaderWriterLockSlim _rwlock; private T _data; public Reader(ReaderWriterLockSlim rwlock, T data) { _ /summary> /// <typeparam name="T"></typeparam> public class Writer<T> where T : IData { private ReaderWriterLockSlim _rwlock; private Random rand = new Random(); private T _data; public Writer(ReaderWriterLockSlim
ReaderWriterLockSlim 原理 ReaderWriterLockSlim允许多个线程同时读取资源,但写操作互斥,且写时不允许读操作,适合读多写少的场景。 _rwLock = new ReaderWriterLockSlim(); public string ReadData() { _rwLock.EnterReadLock(); // 获取读锁 注意 ReaderWriterLockSlim 性能更好,语义更清晰,设计更合理。强烈建议总是使用 ReaderWriterLockSlim 而不是 ReaderWriterLock。 公平性与策略:提供了构造参数 LockRecursionPolicy.NoRecursion / .SupportsRecursion 和 ReaderWriterLockSlim(lockRecursionPolicy 也涉及公平性问题(如读者优先或写者优先,ReaderWriterLockSlim 有机制防止写者饿死)。 优点 允许多个线程同时读取,提高性能。 适合读多写少场景。 缺点 使用复杂,需管理读写锁状态。
读写锁(ReaderWriterLockSlim):允许多个读线程或一个写线程访问资源。计数器(CountdownEvent):用于等待一组任务完成。 using System;using System.Threading;class Program{ static ReaderWriterLockSlim slim = new ReaderWriterLockSlim
autoResetEvent.Set(); } } } 5、读写锁,这种锁允许在有其他程序正在写的情况下读取资源,所以如果资源允许脏读,用这个比较合适 private static ReaderWriterLockSlim LockSlim = new ReaderWriterLockSlim(); private static int lockSlimInt; private static void LockSlimIntAdd 排在第二位 3)第三位lock,临界区也表现出很好的性能,所以在别人说lock性能低的时候请反驳他 4)第四位是原子性变量(Atomic)操作,不过目前只支持变量的自增自减,适用性不强 5)第五位读写锁(ReaderWriterLockSlim
例如,可能要从共享对象中读取 10 个不同的线程,并且通过 System.Threading 命名空间中的 ReaderWriterLockSlim 类授权这些线程同时访问实例,而不导致问题发生。 通过将 ReaderWriterLockSlim 封装到简单的类中,这个问题瞬间解决,不仅重复代码不再会出现,而且还降低了小拼写错误毁一天劳动成果的风险。 图 1 中的类完全基于 lambda 技巧。 图 1:封装 ReaderWriterLockSlim public class Synchronizer<TImpl, TIRead, TIWrite> where TImpl : TIWrite, TIRead { ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); TImpl _shared; public Synchronizer
SynchronizedFile类,对相关操作代码进行线程安全处理,即能解决当前的问题,代码如下:
public class SynchronizedFile
{
private static ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
///
log4net> 自定义日志类 class MyLogger{ //读写锁,当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入 private static readonly ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim(); public static void LogWrite(Exception ex) { if (!