gmutex

    gmutex.Mutex互斥锁对象支持读写控制,互斥锁功能逻辑与标准库sync.RWMutex类似,可并发读但不可并发写。

    接口文档

    https://godoc.org/github.com/gogf/gf/os/gmutex

    1. type Mutex
    2. func New() *Mutex
    3. func (m *Mutex) IsLocked() bool
    4. func (m *Mutex) IsRLocked() bool
    5. func (m *Mutex) IsWLocked() bool
    6. func (m *Mutex) Lock()
    7. func (m *Mutex) LockFunc(f func())
    8. func (m *Mutex) RLock()
    9. func (m *Mutex) RLockFunc(f func())
    10. func (m *Mutex) RUnlock()
    11. func (m *Mutex) TryLock() bool
    12. func (m *Mutex) TryLockFunc(f func()) bool
    13. func (m *Mutex) TryRLock() bool
    14. func (m *Mutex) TryRLockFunc(f func()) bool
    15. func (m *Mutex) Unlock()
    1. 该互斥锁模块最大的特点是支持Try*方法以及*Func方法。
    2. Try*方法用于实现尝试获得特定类型的锁,如果获得锁成功则立即返回true,否则立即返回false,不会阻塞等待,这对于需要使用非阻塞锁机制的业务逻辑非常实用。
    3. *Func方法使用闭包匿名函数的方式实现特定作用域的并发安全锁控制,这对于特定代码块的并发安全控制特别方便,由于内部使用了defer来释放锁,因此即使函数内部产生异常错误,也不会影响锁机制的安全性控制。
    1. package main
    2. "time"
    3. "github.com/gogf/gf/os/glog"
    4. "github.com/gogf/gf/os/gmutex"
    5. )
    6. func main() {
    7. mu := gmutex.New()
    8. for i := 0; i < 10; i++ {
    9. go func(n int) {
    10. mu.Lock()
    11. defer mu.Unlock()
    12. glog.Println("Lock:", n)
    13. time.Sleep(time.Second)
    14. }(i)
    15. }
    16. for i := 0; i < 10; i++ {
    17. go func(n int) {
    18. mu.RLock()
    19. defer mu.RUnlock()
    20. glog.Println("RLock:", n)
    21. time.Sleep(time.Second)
    22. time.Sleep(11 * time.Second)
    23. }

    执行后,终端输出:

    这里使用glog打印的目的,是可以方便地看到打印输出的时间。可以看到,在第3秒的时候,读锁抢占到了机会,由于gmutex.Mutex对象支持并发读但不支持并发写,因此读锁抢占后迅速执行完毕;而写锁依旧保持每秒打印一条日志继续执行。

    1. package main
    2. import (
    3. "time"
    4. "github.com/gogf/gf/os/glog"
    5. "github.com/gogf/gf/os/gmutex"
    6. )
    7. func main() {
    8. mu := gmutex.New()
    9. go mu.LockFunc(func() {
    10. glog.Println("lock func1")
    11. time.Sleep(1 * time.Second)
    12. })
    13. time.Sleep(time.Millisecond)
    14. go mu.LockFunc(func() {
    15. glog.Println("lock func2")
    16. })
    17. time.Sleep(2 * time.Second)

    可以看到,使用*Func方法实现特定作用域的锁控制非常方便。