std::filesystem::create_directory可实现跨平台文件锁,因其目录创建具有原子性(失败当且仅当路径已存在),通过创建唯一命名锁目录(如myapp.lock)并检查返回值即可判断是否持锁,配合pid校验与清理机制避免死锁。

为什么不能直接用 flock 或 LockFileEx?
因为 flock 在 Linux/macOS 上工作良好,但 Windows 不支持;而 LockFileEx 是 Windows 专属,Linux 没这玩意儿。跨平台锁文件必须绕过系统原生接口差异,靠「原子性文件操作 + 重试」模拟互斥——核心是:创建临时文件 → 原子重命名到锁路径 → 成功即持锁。
如何用 std::filesystem::create_directory 实现可移植的独占锁?
这是最轻量、最可靠的方式:利用目录创建的原子性(POSIX 和 Windows 都保证 mkdir 失败当且仅当路径已存在)。把锁抽象成一个带唯一标识的子目录,比如 .lock_12345,而不是普通文件。
-
std::filesystem::create_directory("myapp.lock")返回false表示已被其他进程占用 - 成功返回
true即获得锁,进程退出前必须调用std::filesystem::remove_all("myapp.lock") - 不要用
std::ofstream写空文件再检查存在——竞态明显,两个进程可能同时写成功 - 锁路径建议用绝对路径,避免工作目录差异导致多实例误判
如何处理崩溃导致的死锁?
进程异常退出时锁目录不会自动清理,下次启动会失败。必须加超时和所有权校验:
- 在锁目录里写入当前进程 PID 到
pid文件,再stat/GetFileAttributes检查该 PID 是否仍在运行(Linux 用kill(0, pid),Windows 用OpenProcess) - 若 PID 已不存在,允许主动清理旧锁目录(需先尝试
remove_all,失败则跳过,避免权限问题阻塞) - 不建议依赖时间戳做超时——系统时间可能回拨,且不同机器时间不同步
Windows 下要注意 std::filesystem 的编译配置
MSVC 默认启用 /std:c++17 后 std::filesystem 可用,但链接时必须加 libcpmt.lib(或项目属性 → 配置属性 → 链接器 → 输入 → 附加依赖项填 shlwapi.lib),否则 create_directory 报 LNK2019 错误。
Clang/GCC 用户需确认 -lstdc++fs(GCC 9+)或 -lc++experimental(Clang)已链接,否则运行时报 undefined reference to std::filesystem::create_directory。
真正麻烦的不是实现,而是锁路径的权限继承和清理时机——比如以管理员权限创建的锁,普通用户进程无法删除;又比如多线程程序中,锁释放必须发生在主线程退出前,而非某个 worker 线程结束时。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











