0

0

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

畫卷琴夢

畫卷琴夢

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

|

465人浏览过

|

来源于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");
// 执行写入...

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

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

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

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

典型结构:

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

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

Skybox AI
Skybox AI

一键将涂鸦转为360°无缝环境贴图的AI神器

下载

常见错误:混用锁与 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工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

779

2023.08.22

string转int
string转int

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

463

2023.08.02

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

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

544

2024.08.29

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

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

113

2025.08.29

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

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

200

2025.08.29

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

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

523

2023.08.10

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

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

507

2024.03.15

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

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

292

2024.04.01

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

8

2026.01.30

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号