虽然标准库 Mutex不是可重入锁,但是可以自己实现可重入的Mutex。可重入锁实现的关键点是让锁具有记录当前协程持有这个锁的能力。除了以hack的方式在编译阶段计算偏移量,添加goroutineid外,我们可以利用runtime.Stack
函数获取并记录到goroutineid,记录下获取锁的 goroutineid,它可以实现 Locker 接口。关键代码如下:
n := runtime.Stack(buf[:], false)
// 得到goroutineid
gidStr := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine"))[0]
gid, err := strconv.Atoi(gidStr)