Windows 不支持 syscall.Flock 因其无 flock(2) 系统调用,需用 gofrs/flock 等跨平台库;sync.Mutex 仅限单进程内有效,多进程必须用文件锁。

Go 本身没有跨平台的内置文件锁,syscall.Flock 在 Linux/macOS 可用,但 Windows 不支持;直接用 sync.Mutex 只能保同一进程内 goroutine 安全,无法防止多进程冲突。选错方案会导致“看似加了锁,实则并发写乱”。
用 syscall.Flock 加锁时为什么总在 Windows 报错?
因为 Windows 不支持 flock(2) 系统调用,syscall.Flock 调用会直接返回 ENOSYS 或类似错误。这不是代码写错了,而是系统级不兼容。
- 仅限 Unix-like 系统(Linux、macOS)可用;Windows 下必须换方案
-
LOCK_EX是独占锁,LOCK_SH是共享锁,但 Windows 上二者都无效 - 即使加了
LOCK_NB(非阻塞),错误类型仍是系统不支持,不是“被占用” - 替代方案:用
github.com/gofrs/flock—— 它在 Windows 下自动 fallback 到CreateFile+FILE_SHARE_NONE模拟锁行为
什么时候该用 sync.Mutex,什么时候必须用文件锁?
sync.Mutex 只在单个 Go 进程内有效;只要启动两个独立的 ./myapp 二进制,它就完全失效。
- ✅ 单进程多 goroutine 写同一文件 → 用
sync.Mutex最轻量、无系统依赖 - ✅ 多进程(如 cron 每分钟拉起一次脚本)操作日志/状态文件 → 必须用
flock类系统级锁 - ⚠️ 混用风险:只加
sync.Mutex却部署多个实例,锁形同虚设 - ⚠️ 注意:
os.O_APPEND保证单次Write原子追加,但不防多进程同时写——仍可能行交错(如两行内容挤在同一行)
第三方库 flock 的正确打开方式
推荐直接使用 github.com/gofrs/flock,它封装了系统差异,API 简洁,且默认带超时和重试逻辑。
立即学习“go语言免费学习笔记(深入)”;
- 初始化:
fileLock := flock.New("/path/to/lockfile")—— 锁文件路径可任意,不需预先存在 - 阻塞获取:
locked, err := fileLock.Lock();非阻塞:locked, err := fileLock.TryLock() - 锁释放必须显式调用
fileLock.Unlock(),defer 里放最安全 - 注意:锁文件本身不能是目标业务文件(比如不要锁
data.json自身),应另建data.json.lock - 锁文件权限建议
0600,避免被其他用户干扰
真正容易被忽略的点是:锁的粒度和生命周期。别为了“保险”一直拿着锁做 IO 或网络请求;写入前加锁、写完立刻解锁,中间任何耗时操作(如 HTTP 调用、sleep、复杂计算)都应移出临界区——否则并发吞吐直接归零。










