FileLock能真正跨进程加锁,但必须用FileLock(非SoftFileLock),且所有进程需共享同一绝对路径的锁文件;Windows对锁文件删除更敏感,NFS或权限问题易致锁失效。

filelock 能否真正跨进程加锁
能,但必须用 FileLock(而非 SoftFileLock),且锁文件路径需被所有进程共享。Windows 和 Linux 下行为一致,但 Windows 对文件删除更敏感——锁文件不能被其他进程意外删掉,否则会抛 FileNotFoundError。
常见误判是:本地测试时用多线程模拟多进程,结果看似正常,实际部署后失效。因为 threading.Lock 无法跨进程,而 filelock 的跨进程能力依赖真实文件系统状态。
-
FileLock底层靠os.open(..., os.O_EXCL | os.O_CREAT)实现原子性建锁,这是 POSIX 和 Windows(自 Python 3.8+)都支持的 -
SoftFileLock只做进程内标记,不写磁盘,完全不跨进程,别用它解决跨进程问题 - 锁文件路径建议用绝对路径,避免各进程因工作目录不同导致锁文件位置错位
正确初始化和使用 FileLock 的关键步骤
核心是「同一路径 + 正确上下文管理」。漏掉任一环节都会导致锁失效或死锁。
- 锁对象必须用同一个
FileLock实例(或至少指向同一锁文件路径),不能每个进程 new 一个不同路径的锁 - 必须用
with语句进入临界区,手动调acquire()/release()容易忘记释放或异常跳过 - 锁文件本身无需预先存在,
FileLock会自动创建;但父目录必须存在且可写,否则报FileNotFoundError或PermissionError - 示例:
from filelock import FileLock lock_file = "/tmp/myapp.lock" # 所有进程共用这个路径 with FileLock(lock_file): # 这里读写共享文件、更新数据库状态等 with open("/shared/data.txt", "a") as f: f.write("done by pid {}\n".format(os.getpid()))
为什么有时锁看起来没生效?排查重点
最常踩的坑不是代码写错,而是环境或权限层面的问题。
- Linux 下检查锁文件所在文件系统是否为 tmpfs 或 NFS:tmpfs 支持
O_EXCL,但某些旧版 NFS 不支持原子创建,会导致锁退化为“竞态检测”,失去互斥性 - 多个 Python 进程是否用了不同用户运行?锁文件权限可能限制了其他用户访问,观察
ls -l /tmp/myapp.lock的 owner 和 mode - 进程崩溃未正常退出时,锁文件可能残留。
FileLock不自动清理,下次启动会卡在acquire()—— 可加超时:with FileLock(lock_file):→with FileLock(lock_file).acquire(timeout=5): - 不要在锁内做耗时操作(如网络请求、长循环),否则其他进程会长时间阻塞;把临界区缩到最小,只包真正需要互斥的 IO 或状态变更
与 multiprocessing.Lock 的本质区别
multiprocessing.Lock 是基于共享内存的 IPC 原语,只在 fork 出的子进程中有效;一旦进程是独立启动(比如两个 python worker.py),它们之间根本没有共享内存段,multiprocessing.Lock 完全无效。
-
filelock.FileLock是唯一轻量、无依赖、跨任意进程(无论启动方式)的方案 - 不需要额外服务(如 Redis)、不依赖消息队列、不强制要求进程有父子关系
- 性能上比内存锁慢几个数量级,但对大多数配置更新、日志轮转、定时任务防重跑等场景已足够
- 注意:若程序要支持容器化部署,确保锁路径挂载为 volume,否则各容器看到的是各自文件系统里的“同名”锁文件,实际不共享
锁文件路径是否被所有进程真实共享,是整个机制成立的前提。其他所有问题,几乎都源于这个前提没被验证。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











