You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于标准C++的共享文件读写同步方案:能否防竞争、避死锁?

跨进程文件读写同步方案分析

需求背景

协调一个极少更新的写入进程(writer)和频繁读取的读取进程(reader)对共享文本文件的访问,要求完全基于标准C++实现,禁止使用Unix flock、Windows LockFile等平台特定锁功能。

现有方案实现

Reader进程代码

bool reader(const std::filesystem::path &f)
{
  namespace fs = std::filesystem;  

  // Check for write lock.
  auto write_lock_file = fs::path(f).replace_extension(".write.lock");
  if (fs::exists(write_lock_file))
    return false;  // writer is active, aborting

  // Create read lock.
  auto read_lock_file = fs::path(f).replace_extension(".read.lock");
  std::ofstream(read_lock_file).close();

  // Recheck for write lock.
  // When the writer creates the write lock, readers that check for the write
  // lock will immediately abort, ensuring the writer can proceed as soon as
  // it's ready.
  if (fs::exists(write_lock_file))
  {
    fs::remove(read_lock_file);  // cleanup
    return false;
  }

  // READ WHAT NEEDED FROM f

  fs::remove(read_lock_file);
  return true;
}

Writer进程代码

void writer(const std::filesystem::path &f)
{
  namespace fs = std::filesystem;

  // Create write lock.
  auto write_lock_file = fs::path(f).replace_extension(".write.lock");
  std::ofstream(write_lock_file).close();

  // Wait for readers to finish.
  // After creating the write lock, the writer waits for all readers to finish
  // before proceeding. This ensures that existing readers are not interrupted,
  // but no new readers can start.
  auto read_lock_file = fs::path(f).replace_extension(".read.lock");
  while (fs::exists(read_lock_file))
    std::this_thread::sleep_for(100ms);

  // WRITE NEW DATA INTO f
}

方案核心逻辑

读写进程通过各自的锁文件标记活动状态:

  • Reader操作前先检查写锁文件,创建读锁后再次检查写锁,避免竞争;
  • Writer创建写锁后,等待所有读锁消失再写入,新Reader会因检测到写锁直接放弃。

问题解答

1. 该方案能否防止读写进程间的竞争条件?

不能,存在多个核心缺陷导致竞争或功能失效:

  • 多Reader场景同步逻辑错误:方案使用单个.read.lock文件标记所有Reader状态,但每个Reader完成后都会删除该文件。当多个Reader并发读取时,第一个完成的Reader会提前删除锁文件,Writer会误判所有Reader已结束并开始写入,导致后续仍在读取的Reader与Writer发生读写数据竞争。
  • Writer未清理写锁文件:现有Writer代码创建.write.lock后未执行删除操作,写入完成后写锁会永久存在,所有后续Reader都会因检测到写锁直接返回读取失败,完全无法访问文件。
  • 极端场景下的竞争窗口:虽然Reader做了两次写锁检查,但在第一次检查写锁不存在到创建读锁的时间窗口内,若Writer恰好创建写锁,Reader虽会放弃读取,但该依赖后续检查的逻辑存在极端情况下的竞争风险(不过此场景不会导致读写同时执行,仅会让Reader读取失败)。

2. 能否避免死锁或长时间阻塞?

正常流程下不会死锁,但存在长时间阻塞风险及功能失效问题:

  • 死锁风险:正常执行流程中无死锁可能:
    • 若Writer先创建写锁,新Reader会直接检测到写锁并放弃,不会创建读锁;已有Reader完成读取后删除读锁,Writer最终可继续执行。
    • 若Reader先创建读锁,Writer创建写锁后会等待读锁消失,Reader第二次检查到写锁后会删除读锁并放弃,Writer也能继续。
      (进程异常崩溃导致锁文件未清理的情况,题目说明作为单独问题考量,不在此讨论范围内)
  • 长时间阻塞风险:若Writer创建写锁后,存在Reader长时间持有读锁未释放(如Reader进程挂起、读取操作耗时极长),Writer会进入无限循环等待,导致长时间阻塞。不过题目中Reader是“频繁读取”,该场景概率较低。

内容的提问来源于stack exchange,提问作者manlio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:19:50