您的位置:首页 >C# 文件锁公平性解析与实现方法
发布于2026-03-17 阅读(0)
扫一扫,手机访问
FileShare不保证公平性,仅控制文件打开权限;真正的并发读写协调需用ReaderWriterLockSlim等上层机制配合统一锁实例和规范释放。

FileStream 本身不保证读写顺序很多人以为只要用 FileShare.ReadWrite 就能“公平”处理并发访问,其实这是误解。.NET 的 FileStream 底层依赖操作系统文件句柄,而 Windows/Linux 对文件共享的调度是无序的——先抢到句柄的线程/进程就上,不管它是要读还是写。所谓“公平”,必须靠上层逻辑控制。
FileShare 只决定能否同时打开,不干预后续 I/O 的执行时机或优先级new FileStream(...) 时,构造函数返回不代表已获得磁盘访问权,真正阻塞可能发生在第一次 Read() 或 Write()ReaderWriterLockSlim 做内存协调,但注意它不锁文件本身真正的公平读写锁得自己组装:用 ReaderWriterLockSlim 管理“谁可以发起文件操作”,再配合实际的 FileStream 操作。但它只锁代码路径,不锁磁盘,所以必须确保所有文件访问都经过同一把锁实例,且不能绕过。
ReaderWriterLockSlim 实例,不能每次操作都 new 一个EnterReadLock() + TryEnterReadLock() 配合超时,避免写线程长期被饿死EnterWriteLock(),且内部要尽快完成 —— 锁住期间其他读写全卡住finally 块里调用 ExitReadLock() 或 ExitWriteLock(),否则锁泄漏会导致整个系统僵死var rwLock = new ReaderWriterLockSlim();
// 读
rwLock.EnterReadLock();
try {
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
// ...读取
} finally { rwLock.ExitReadLock(); }
多数场景下,与其费力模拟公平,不如换思路:让写操作走独占、原子、低延迟路径,读操作尽量缓存或降级。例如日志文件、配置快照这类典型用例,写入用 FileMode.Create + FileAccess.Write + FileShare.None,读取则从内存缓存或副本拿。
FileMode.Append 虽然允许并发打开,但多线程写入仍可能交错(Windows 下尤其明显),不是线程安全的追加FileStream.Lock() 手动锁住文件区域,但跨进程无效,且容易死锁MemoryMappedFile)+ 自定义读写计数器,比纯 FileStream 更可控ReaderWriterLockSlim,得用命名同步原语ReaderWriterLockSlim 是进程内锁,跨进程时完全失效。如果你的程序有多个实例(比如 Windows 服务 + GUI 工具同时操作同一文件),必须升级到系统级同步机制。
Mutex 或 Semaphore 配合命名前缀(如 "Global\\MyApp_FileAccess"),注意权限问题,普通用户可能无法访问 Global\ 命名空间EventWaitHandle 可以做读写信号量,但需要你自己维护读计数器和写状态,容易出错NamedPipeServerStream),把文件操作收口到一个守护进程里,其他进程只发请求公平从来不是文件系统的默认属性,而是你对访问路径、资源粒度和错误容忍度权衡后的结果。最容易被忽略的一点:当多个线程都在等同一个文件锁时,它们的等待顺序取决于 OS 调度器,而不是你代码里的 EnterReadLock() 调用顺序。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9