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.")

}

牙小木木
1.5k 声望80 粉丝

iamtb.cn