flock 是建议性锁,不具备强制性。进程在文件(inode)放了锁,其他进程可以知道。如果有进程不讲武德,不判断锁的存在,直接进行文件件操作也是允许的。
flock 常用于文件数据竞争管理,也会用来检测进程是否存在(进程终止,锁自动释放)。
主要三种操作类型:
- LOCK_SH,共享锁,多个进程可以使用同一把锁,常被用作读共享锁;
- LOCK_EX,排他锁,同时只允许一个进程使用,常被用作写锁;
- LOCK_UN,释放锁;
LOCK_NB 参数,在获取锁失败,不会等待,立即返回错误。
下面用 Go 验证 flock
注意:Windows 不支持 pid 锁。
flock1.go
func main() {
var f = "app.log"
file, err := os.OpenFile(f, os.O_RDWR, os.ModeExclusive)
if err != nil {
panic(err)
}
defer file.Close()
// 调用系统调用加锁
err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
if err != nil {
panic(err)
}
defer syscall.Flock(int(file.Fd()), syscall.LOCK_UN)
// 读取文件内容
all, err := ioutil.ReadAll(file)
if err != nil {
panic(err)
}
fmt.Printf("%s", all)
time.Sleep(time.Second * 10) //模拟耗时操作
}
运行:
go run flock1.go
查看锁
$ lslocks
可以看到 app.log 锁已经加上了
flock1 895 FLOCK 5B WRITE 0 0 0 /data/go-workspace/test/app.log
再次运行 flock1.go
报错资源暂时不可用
panic: resource temporarily unavailable
goroutine 1 [running]:
main.main()
/data/go-workspace/test/flock1.go:22 +0x2d6
exit status 2
参考