P4-全局唯一串行文件写入控制装置

文档发表:2026-06-24 · 阅读:112 · 更新:2026-08-05

学术论文 · 四川的梦科技有限公司 · 2026-07-27


摘要

AI 编程助手中,大语言模型在单次回复中可能并行调用多个工具同时修改文件,导致经典的并发写入问题:脏写(dirty write)、丢失更新(lost update)、以及读-改-写竞态(read-modify-write race)。传统文件锁方案(flock/mutex/CAS)或粒度过粗阻塞无关操作,或仅检测冲突不自动解决。本文提出全局唯一写机器(qwr)——基于 per-file Promise 串行队列 + 全局命令屏障 + CAS 队列内重读 + 外部修改检测 + 快照自更新的五层防御体系。该方案保证零脏写、零丢失更新、零死锁、零误报,同文件自动排队、不同文件并行执行。


1. 引言

在 qqq-shell-v2 IDE 中,AI 代理可通过 5 种工具修改文件系统:edit_file、write_file、create_file、delete_file、run_command。单次 AI 回复可能并行调用其中多个。以下竞态场景必须处理:

  1. 同文件并发 edit:AI 同时 edit_file('foo.js', ...) ×2 → 后者可能在前者修改基础上操作失效
  2. write 与 run_command 竞态:write_file('bar.py', ...) 过程中 run_command('python bar.py') 执行 → 读到半写文件
  3. 外部修改:用户在编辑器中手动修改文件,AI 不知情 → edit_file 基于过期快照

现有方案:

方案缺陷
flock/fcntl仅防多进程,不防同进程异步竞态
全局 Mutex阻塞所有无关文件操作,性能灾难
CAS 乐观锁仅检测冲突 → AI 收到冲突错误需手动重试
无锁后写覆盖先写,"丢失更新"

2. 五层防御体系

层1:per-file 串行队列 (_qw Map)

_qw: Map<filePath, Promise链>

同文件的所有写操作排队:后一操作等待前一操作的 Promise 完成。不同文件并行执行。这保证了同文件串行、不同文件并行的最优并发度。

层2:全局命令屏障 (_co/_ac 双向门)

命令执行(run_command)必须等待所有正在进行的写操作完成。反之,写操作也必须等待所有正在执行的命令完成。双向门用两个计数器 + Promise 实现,无死锁(循环等待检测)。

层3:CAS 队列内重读

edit_file 在队列内被调度执行时,不是基于 AI 提供的旧快照,而是重新读取文件当前内容后再执行 find/replace。这消除了"AI 基于过期快照编辑"的竞态窗口。

层4:外部修改检测

read_file 记录文件的 {mtime, size}。write_file 执行前对比当前 {mtime, size} 与快照 → 不匹配则拒绝写入,返回冲突信息。

层5:快照自更新

edit/create → 自动更新快照 ({mtime, size})。delete → 清除快照。确保层4的检测基准始终最新。


3. 核心数据结构

_qw: Map<path, Promise链>     // per-file 写队列
_co: number                    // 正在执行的命令计数
_ac: number                    // 正在执行的写操作计数
_snapshots: Map<path, {mtime, size}>  // 文件快照
_qgc: Set<Promise>             // 命令队列

3.1 写操作入口 (write/edit/create/delete)

1. 如果 _ac > 0 → await _co 归零(等命令完成)
2. _ac++
3. 从 _qw.get(path) 获取该文件队列的尾 Promise
4. 创建新 Promise 链: prevPromise.then(执行实际写操作)
5. _qw.set(path, newPromise)
6. await newPromise
7. _ac--

3.2 命令入口 (run_command)

1. 如果 _ac > 0 → await _ac 归零(等写完成)
2. _co++
3. 执行命令
4. _co--

4. 正确性证明

4.1 无脏写

per-file 串行队列保证同文件操作严格顺序执行。假设两个 edit_file('foo.js') 并发调用:

  • edit#1 先入队 → 执行 → 更新快照
  • edit#2 在队列中等待 → edit#1 完成后 → 重读文件(层3 CAS)→ 基于最新内容执行

→ edit#2 不会覆盖 edit#1 的修改

4.2 无丢失更新

层4 外部修改检测:若用户在 AI 的 read_file 和 write_file 之间手动修改了文件 → {mtime, size} 不匹配 → 拒绝 write → 返回错误。

4.3 无死锁

双向门 (_co/_ac) 只在命令等写完成、写等命令完成时使用,不存在循环等待(不存在"命令等写、写等命令"的环形依赖,因为同一时刻只有一个方向在等待)。

4.4 无误报

层5 快照自更新确保:AI 自己的写操作完成后立即更新快照 → 下一次 read_file → write_file 不会因为 AI 自己刚才的修改而被层4 误拒。


5. 性能分析

场景无 qwr有 qwr额外开销
单文件 5 次顺序 edit~250ms~260ms+4% (队列串联)
5 个不同文件并行 edit~60ms~62ms+3% (不同文件并行)
3 edit + 1 run_command~180ms~190ms+5% (屏障等待)

开销主要来自层3 的重读文件(~5-10ms/次),但这是保证正确性的必要代价。


6. 结论

全局唯一写机器(qwr)以五层递进防御,在 AI 多工具并发场景中提供了零脏写、零丢失更新的文件系统安全保障。per-file 队列 + 全局屏障的组合设计在保证正确性的同时最大化并发度。该方案可推广至任何需要多代理并发文件操作的 IDE 或协作编辑系统。


参考文献

[1] Lamport, L. "Time, Clocks, and the Ordering of Events in a Distributed System." CACM 1978. [2] Bernstein, P.A. et al. "Concurrency Control and Recovery in Database Systems." 1987. [3] PostgreSQL Documentation — Serializable Snapshot Isolation. postgresql.org. [4] qqq-shell-v2 架构文档 § qwr 机器, 2026.