Go语言如何实现文件独占锁 保证同一时间仅一个进程可写入
1 os.ModeExclusive 作用说明
os.ModeExclusive 是Windows平台专属的权限位,类Unix系统(Linux、macOS等)上该参数会被内核忽略。它的作用是创建文件时标记为独占访问模式,只有创建该文件的进程可以持有文件句柄,其他进程无论权限如何都无法打开该文件,这也是你第二次运行程序无法访问文件的原因。该参数的设计逻辑是完全禁止多进程访问,和你需要的「读共享、写独占」需求不匹配,不建议使用。
2 flock 咨询锁的适用场景说明
你看到的评论提到的「无法提供操作系统级别的强制锁」是事实,但该限制对你的场景几乎没有影响:
flock 实现的是咨询锁(协同锁),所有访问目标文件的进程都需要主动调用加锁接口检查锁状态才会生效;而强制锁由内核强制拦截访问,不需要进程主动配合。
你开发的是自主可控的私密存储工具,所有访问.secrets文件的进程都是你的程序实例,只要你在代码里统一加上加锁逻辑,咨询锁完全可以满足并发控制要求。
3 读写独占锁实现方案
你需要的「多进程可同时读、同一时间仅一个进程可写」的需求,正好对应flock提供的两种锁类型:
- 共享锁(LOCK_SH):多个进程可以同时持有,用于读操作
- 排他锁(LOCK_EX):同一时间仅一个进程可以持有,用于写操作
你之前用0744打开文件的写法,只是设定了文件系统的权限位,仅控制不同用户的访问权限,无法限制同一用户下多个进程的并发访问,所以才会出现任意进程都可读写的问题。存储敏感文件建议用0600权限,仅文件所有者可读写,安全性更高。
基础加锁接口示例
// 加共享读锁(读取文件时调用) func lockRead(file *os.File) error { return syscall.Flock(int(file.Fd()), syscall.LOCK_SH) } // 加排他写锁(写入文件时调用) func lockWrite(file *os.File) error { return syscall.Flock(int(file.Fd()), syscall.LOCK_EX) } // 解锁(也可以直接关闭文件,系统会自动释放锁) func unlock(file *os.File) error { return syscall.Flock(int(file.Fd()), syscall.LOCK_UN) }
读操作流程
f, err := os.OpenFile(".secrets", os.O_RDONLY, 0600) if err != nil { // 错误处理 } defer f.Close() // 加共享读锁,多个进程可同时加锁成功 if err := lockRead(f); err != nil { // 错误处理 } defer unlock(f) // 执行读取操作
写操作流程
f, err := os.OpenFile(".secrets", os.O_RDWR|os.O_CREATE, 0600) if err != nil { // 错误处理 } defer f.Close() // 加排他写锁,同一时间仅一个进程加锁成功 if err := lockWrite(f); err != nil { // 错误处理 } defer unlock(f) // 执行写入操作,写完后调用Sync()刷盘避免数据丢失 // _, err = f.Write(你的存储内容) // f.Sync()
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

