讲师中心 微信公众号
AI工具推荐 视频效率加速

c# 如何用c#实现读写者问题 Reader-Writer Problem

落磊小哥_5979

落磊小哥_5979

发布时间:2026-01-30 10:29:02

|

525人浏览过

|

来源于php中文网

原创

读写者问题的C#实现难点在于ReaderWriterLockSlim默认不保证写优先,易致写饥饿;需显式启用写优先模式、避免混用async/await,并在强时效场景下手动实现FIFO调度。

c# 如何用c#实现读写者问题 reader-writer problem

什么是读写者问题的 C# 实现难点

读写者问题不是 .NET 内置的同步原语,ReaderWriterLockSlim 是最接近、也最常被误用的方案——它默认不保证写优先,且读线程饥饿时不会自动让写线程插队。很多开发者直接套用 EnterReadLock() / EnterWriteLock() 就以为解决了,结果在高并发读+偶发写的场景下,写操作被无限推迟。

用 ReaderWriterLockSlim 实现写优先(避免写饥饿)

必须显式启用写优先模式,否则读线程只要持续到来,写线程永远等不到机会。关键在于构造时传入 LockRecursionPolicy.NoRecursion 并设置 UseSpinWait = true 提升响应,但核心是调用 EnterUpgradeableReadLock() + EnterWriteLock() 组合来模拟“检查-升级”逻辑。

var rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
// 写操作(带超时防死锁)
bool acquired = false;
try
{
    acquired = rwLock.TryEnterWriteLock(1000); // 1秒超时
    if (!acquired) throw new TimeoutException("Write lock timeout");
<pre class='brush:php;toolbar:false;'>// 执行写入...

} finally { if (acquired) rwLock.ExitWriteLock(); }

  • 不要用 EnterWriteLock() 无参版本——可能无限阻塞
  • 读操作可用 TryEnterReadLock(int) 配合重试,但读多写少时建议直接用 EnterReadLock()
  • 升级路径(读→写)必须通过 EnterUpgradeableReadLock(),不能先读再抢写锁,否则引发死锁

手动实现公平读写锁(需要严格 FIFO 调度)

当 ReaderWriterLockSlim 的“写优先”仍不够用(比如要求第 N 个写请求必须在前 N−1 个写完成后再执行),就得用 ConcurrentQueue<task></task> + SemaphoreSlim 手动编排。本质是把读/写请求转为任务,由单一线程调度器按入队顺序分发。

典型结构:

Microsoft Skill Creator
Microsoft Skill Creator

使用 Learn MCP 工具为 Microsoft 技术创建代理技能。当用户想要创建教授代理任何 Microsoft 技术的技能时使用。

下载
  • 一个 SemaphoreSlim 控制「当前是否允许新读」(初始值 1)
  • 一个 int _activeReaders 计数器 + object _readLock 保护它
  • 所有写请求先入队,写任务执行前先 WaitAsync() 等待读计数归零
  • 每个读任务执行前先 WaitAsync() 获取读许可,完成后释放

这种实现在吞吐量上不如 ReaderWriterLockSlim,但能确保写请求不被读流淹没——适合配置更新、状态切换等强时效性场景。

常见错误:混用锁与 async/await

ReaderWriterLockSlim 不支持异步等待。下面这段代码会出问题:

// ❌ 错误:不能在 async 方法里直接 await 锁
await rwLock.EnterReadLockAsync(); // 编译不过!没有这个方法

正确做法只有两种:

  • 在同步上下文中使用(如 ASP.NET Core 中标记 [NonAction] 或用 Task.Run(() => { ... }) 包裹锁内逻辑)
  • 改用 AsyncReaderWriterLock(第三方 NuGet 包,如 Microsoft.VisualStudio.Threading 提供的 AsyncReaderWriterLock)
  • 更推荐:把 I/O 操作移出锁区,只锁内存结构修改,例如先读数据 → 解锁 → await DB 查询 → 再锁 → 更新缓存

真正难的不是写出来,而是判断该不该用写优先、要不要放弃 ReaderWriterLockSlim 改用手动队列——这取决于你能否容忍写操作延迟超过 100ms。如果不能,就别碰默认模式。

热门AI工具

更多
超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

码上飞
码上飞 Hot

一款基于自然语言的AI应用开发平台,可根据用户描述自动生成应用程序,帮助个人和团队快速完成应用原型与开发。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

7139

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3405

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

4468

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

3005

2025.08.29

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4638

2023.08.10

vscode和visualstudio的区别
vscode和visualstudio的区别

Visual Studio是一款功能强大的集成开发环境(IDE),适用于专业开发人员进行复杂项目的构建。而VSCode则是一款轻量级的代码编辑器,更适合各种规模的项目开发。想了解更多vscode的相关内容,可以阅读本专题下面的文章。

1156

2024.03.15

vscode和visualstudio对比分析
vscode和visualstudio对比分析

VSCode是一款轻量级代码编辑器,界面简洁,支持广泛的编程语言,适合个人开发者和小团队。而Visual Studio是一款全功能IDE,界面复杂但功能丰富,适合大型项目开发和团队协作,特别是面向.NET开发。想了解更多vscode的相关内容,可以阅读本专题下面的文章。

2092

2024.04.01

vsd文件打开方法
vsd文件打开方法

vsd文件打开方法有使用Microsoft Visio软件、使用Microsoft Visio查看器、转换为其他格式等。想了解更多vsd文件相关内容,可以阅读本专题下面的文章。

1382

2023.10.30

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

0

2026.11.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn