golang文件锁
在程序并发运行时,有时会限制多个线程操作同一个文件,这是就需要文件锁,类似于线程中的锁。不同的系统平台有不同的实现,这里以Linux为例。
先来说一下锁的集中情况,在go语言的syscall包中定义了下面几个常量
LOCK_EX = 0x2
LOCK_NB = 0x4
LOCK_SH = 0x1
LOCK_UN = 0x8
- LOCK_EX指排他锁,也就是同时只允许一个线程使用
- LOCK_NB指其他线程遇到一个排他锁会直接返回error,而不加该参数时线程会等待锁释放,利用这个参数可以简单的检测一个文件是否被占用
- LOCK_SH指共享锁,多个线程都可以使用
- LOCK_UN指释放一个锁
而在go语言中对一个文件锁的操作主要借助syscall的Flock方法
func Flock(fd int, how int) (err error) {
_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
这里我们只要传入文件标识符fd和锁的操作参数how即可,如:
f, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0644)
syscall.Flock(int(l.f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
由于对于不同平台有不同实现,上面只适用于linux,为了解决各种平台的适配,在Prometheus的tsdb中有一套文件锁的实现,可以直接拿过来用或参考其相关实现。
题图来自unsplash:https://unsplash.com/photos/sUIrV6z9JCs