github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgProcessMutex/mutex.go (about) 1 // +build linux darwin 2 3 package kmgProcessMutex 4 5 import ( 6 "github.com/bronze1man/kmg/kmgErr" 7 "os" 8 "path/filepath" 9 "syscall" 10 ) 11 12 type FileMutex struct { 13 isOwner bool 14 filePath string 15 Name string 16 f *os.File 17 } 18 19 // flock 加锁,会将锁(系统级别)挂在某个文件上,只要有进程给某个文件挂上了锁,则其他进程(包括本进程)就必须解锁 20 func (fm *FileMutex) Lock() { 21 kmgErr.PanicIfError(syscall.Flock(int(fm.getFd()), int(syscall.LOCK_EX))) 22 } 23 24 // flock 加的锁,有两种方式解除锁: 25 // 1.加锁的进程退出了,锁自动释放 26 // 2.在进程内,使用 fd0 挂上的锁,显式的使用 fd0 解锁; 27 // 注意:同一个进程内,fd0 和 fd1 指向同一个文件(fd1 不是 fd0 的副本),若是 fd0 挂上的锁,必须用 fd0 来解锁,fd1 无法解锁 28 func (fm *FileMutex) UnLock() { 29 kmgErr.PanicIfError(syscall.Flock(fm.getFd(), int(syscall.LOCK_UN))) 30 } 31 32 func (fm *FileMutex) getFd() int { 33 if fm.f != nil { 34 return int(fm.f.Fd()) 35 } 36 if fm.Name == "" { 37 panic(`no specialed file [Name] for locking,Example:l := &kmgProcessMutex.FileMutex{Name: "abc"}`) 38 } 39 fm.filePath = filepath.Join("/tmp", fm.Name) 40 var err error 41 fm.f, err = os.OpenFile(fm.filePath, os.O_CREATE|os.O_EXCL, os.FileMode(0777)) 42 if err == nil { 43 return int(fm.f.Fd()) 44 } 45 if os.IsExist(err) { 46 fm.f, err = os.OpenFile(fm.filePath, os.O_RDONLY, os.FileMode(0777)) 47 } else { 48 kmgErr.LogErrorWithStack(err) 49 } 50 return int(fm.f.Fd()) 51 }