package main
import (
"fmt"
"github.com/petermattis/goid"
"sync"
"sync/atomic"
)
// Go version: V1.21.0
type ReentryMutex struct {
sync.Mutex
owner int64// 以后锁的拥有者 goroutineid
reentry int32// 重入次数
}
func (r *ReentryMutex)Lock(){gid:=goid.Get()
// 如果锁的拥有者曾经是以后 goroutine,记录下他曾经重入的次数
if atomic.LoadInt64(&r.owner)==gid{
r.reentry++
return
}
r.Mutex.Lock()
atomic.StoreInt64(&r.owner,gid)
// 初始化可拜访次数
r.reentry=1
}
func (r *ReentryMutex) Unlock(){gid:=goid.Get()
// 如果解锁协程不是以后协程的拥有者,就 panic
if atomic.LoadInt64(&r.owner)!=gid{panic(any(fmt.Sprintf("wrong the owner(%d): %d!",r.owner,gid)))
}
r.reentry--
if r.reentry==0{atomic.StoreInt64(&r.owner,-1)
r.Mutex.Unlock()}
}
func main() {
var wg sync.WaitGroup
reentryMutex:=ReentryMutex{}
for i := 0; i < 5; i++ {wg.Add(1)
go func(index int) {defer wg.Done()
reentryMutex.Lock()
defer reentryMutex.Unlock()
fmt.Printf("Goroutine %d acquired the lock.\n", index)
reentryMutex.Lock()
defer reentryMutex.Unlock()
fmt.Printf("Goroutine %d acquired the lock again.\n", index)
}(i)
}
wg.Wait()
fmt.Println("All goroutines have finished.")
}