github.com/songzhibin97/gkit@v1.2.13/internal/sys/mutex/recursive_mutex.go (about) 1 package mutex 2 3 import ( 4 "fmt" 5 "sync" 6 "sync/atomic" 7 8 "github.com/songzhibin97/gkit/internal/sys/goid" 9 ) 10 11 // RecursiveMutex 包装一个Mutex,实现可重入 12 type RecursiveMutex struct { 13 sync.Mutex 14 owner int64 // 当前持有锁的goroutine id 15 recursion int32 // 这个goroutine 重入的次数 16 } 17 18 func (m *RecursiveMutex) Lock() { 19 gid := goid.GetGID() 20 // 如果当前持有锁的goroutine就是这次调用的goroutine,说明是重入 21 if atomic.LoadInt64(&m.owner) == gid { 22 m.recursion++ 23 return 24 } 25 m.Mutex.Lock() 26 // 获得锁的goroutine第一次调用,记录下它的goroutine id,调用次数加1 27 atomic.StoreInt64(&m.owner, gid) 28 m.recursion = 1 29 } 30 31 func (m *RecursiveMutex) Unlock() { 32 gid := goid.GetGID() 33 // 非持有锁的goroutine尝试释放锁,错误的使用 34 if atomic.LoadInt64(&m.owner) != gid { 35 panic(fmt.Sprintf("wrong the owner(%d): %d!", m.owner, gid)) 36 } 37 // 调用次数减1 38 m.recursion-- 39 if m.recursion != 0 { // 如果这个goroutine还没有完全释放,则直接返回 40 return 41 } 42 // 此goroutine最后一次调用,需要释放锁 43 atomic.StoreInt64(&m.owner, -1) 44 m.Mutex.Unlock() 45 }