gmutex
gmutex
模块是基于atomic
+ channel
实现的高级互斥锁模块,支持更丰富的互斥锁特性。
...
- 该互斥锁模块最大的特点是支持
Try*
方法以及*Func
方法。 Try*
方法用于实现尝试获得特定类型的锁,如果获得锁成功则立即返回true
,否则立即返回false
,不会阻塞等待,这对于需要使用非阻塞锁机制的业务逻辑非常实用。*Func
方法使用闭包匿名函数的方式实现特定作用域的并发安全锁控制,这对于特定代码块的并发安全控制特别方便,由于内部使用了defer
来释放锁,因此即使函数内部产生异常错误,也不会影响锁机制的安全性控制。
基准测试
gmutex.Mutex
与标准库的sync.Mutex
及sync.RWMutex
的基准测试对比结果: gmutex_bench_test.go
goos: linux
goarch: amd64
pkg: github.com/gogf/gf/os/gmutex
Benchmark_Mutex_LockUnlock-4 50000000 31.5 ns/op
Benchmark_RWMutex_LockUnlock-4 30000000 54.1 ns/op
Benchmark_RWMutex_RLockRUnlock-4 50000000 27.9 ns/op
Benchmark_GMutex_LockUnlock-4 50000000 27.2 ns/op
Benchmark_GMutex_TryLock-4 100000000 16.7 ns/op
Benchmark_GMutex_RLockRUnlock-4 50000000 38.0 ns/op
Benchmark_GMutex_TryRLock-4 100000000 16.8 ns/op
示例1,基本使用
package main
import (
"time"
"github.com/gogf/gf/os/glog"
"github.com/gogf/gf/os/gmutex"
)
func main() {
mu := gmutex.New()
for i := 0; i < 10; i++ {
go func(n int) {
mu.Lock()
defer mu.Unlock()
glog.Println("Lock:", n)
time.Sleep(time.Second)
}(i)
}
for i := 0; i < 10; i++ {
go func(n int) {
mu.RLock()
defer mu.RUnlock()
glog.Println("RLock:", n)
time.Sleep(time.Second)
}(i)
}
time.Sleep(11 * time.Second)
}
...
这里使用glog
打印的目的,是可以方便地看到打印输出的时间。可以看到,在第3秒的时候,读锁抢占到了机会,由于gmutex.Mutex
对象支持并发读但不支持并发写,因此读锁抢占后迅速执行完毕;而写锁依旧保持每秒打印一条日志继续执行。
示例2,*Func
使用
package main
import (
"time"
"github.com/gogf/gf/os/glog"
"github.com/gogf/gf/os/gmutex"
)
func main() {
mu := gmutex.New()
go mu.LockFunc(func() {
glog.Println("lock func1")
time.Sleep(1 * time.Second)
})
time.Sleep(time.Millisecond)
go mu.LockFunc(func() {
glog.Println("lock func2")
})
time.Sleep(2 * time.Second)
}
...