mirror of https://github.com/q191201771/naza
[feat] package nazasync:新增的package,其中的Mutex可用于debug锁方面的问题
parent
90b29a0b9e
commit
a24a0d5d7f
@ -0,0 +1,33 @@
|
||||
// Copyright 2021, Chef. All rights reserved.
|
||||
// https://github.com/q191201771/naza
|
||||
//
|
||||
// Use of this source code is governed by a MIT-style license
|
||||
// that can be found in the License file.
|
||||
//
|
||||
// Author: Chef (191201771@qq.com)
|
||||
|
||||
package nazasync
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"runtime"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// NOTICE copy from https://github.com/golang/net/blob/master/http2/gotrack.go
|
||||
|
||||
var ErrObtainGoroutineID = errors.New("nazasync: obtain current goroutine id failed")
|
||||
|
||||
func CurGoroutineID() (int64, error) {
|
||||
var goroutineSpace = []byte("goroutine ")
|
||||
|
||||
b := make([]byte, 128)
|
||||
b = b[:runtime.Stack(b, false)]
|
||||
b = bytes.TrimPrefix(b, goroutineSpace)
|
||||
i := bytes.IndexByte(b, ' ')
|
||||
if i < 0 {
|
||||
return -1, ErrObtainGoroutineID
|
||||
}
|
||||
return strconv.ParseInt(string(b[:i]), 10, 64)
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// Copyright 2021, Chef. All rights reserved.
|
||||
// https://github.com/q191201771/naza
|
||||
//
|
||||
// Use of this source code is governed by a MIT-style license
|
||||
// that can be found in the License file.
|
||||
//
|
||||
// Author: Chef (191201771@qq.com)
|
||||
|
||||
package nazasync
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/q191201771/naza/pkg/assert"
|
||||
|
||||
"github.com/q191201771/naza/pkg/nazalog"
|
||||
)
|
||||
|
||||
func TestCurGoroutineID(t *testing.T) {
|
||||
max := 5
|
||||
|
||||
gid, err := CurGoroutineID()
|
||||
assert.Equal(t, nil, err)
|
||||
nazalog.Infof("> main. gid=%d", gid)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(max)
|
||||
for i := 0; i < max; i++ {
|
||||
go func(ii int) {
|
||||
gid, err := CurGoroutineID()
|
||||
assert.Equal(t, nil, err)
|
||||
nazalog.Infof("> %d. gid=%d", ii, gid)
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
gid, err = CurGoroutineID()
|
||||
assert.Equal(t, nil, err)
|
||||
nazalog.Infof("< main. gid=%d", gid)
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
// Copyright 2021, Chef. All rights reserved.
|
||||
// https://github.com/q191201771/naza
|
||||
//
|
||||
// Use of this source code is governed by a MIT-style license
|
||||
// that can be found in the License file.
|
||||
//
|
||||
// Author: Chef (191201771@qq.com)
|
||||
|
||||
package nazasync
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/q191201771/naza/pkg/unique"
|
||||
|
||||
"github.com/q191201771/naza/pkg/nazalog"
|
||||
)
|
||||
|
||||
// 用于debug锁方面的问题
|
||||
|
||||
const unlockedGid = 0
|
||||
|
||||
type Mutex struct {
|
||||
core sync.Mutex
|
||||
|
||||
mu sync.Mutex
|
||||
uniqueKey string
|
||||
gid int64
|
||||
}
|
||||
|
||||
func (m *Mutex) Lock() {
|
||||
m.mu.Lock()
|
||||
if m.uniqueKey == "" {
|
||||
m.uniqueKey = unique.GenUniqueKey("MUTEX")
|
||||
}
|
||||
gid, _ := CurGoroutineID()
|
||||
if gid == m.gid {
|
||||
nazalog.Out(nazalog.LevelError, 3, fmt.Sprintf("[%s] recursive lock. gid=%d", m.uniqueKey, gid))
|
||||
}
|
||||
m.gid = gid
|
||||
m.mu.Unlock()
|
||||
|
||||
nazalog.Out(nazalog.LevelDebug, 3, fmt.Sprintf("[%s] > Lock(). gid=%d", m.uniqueKey, gid))
|
||||
m.core.Lock()
|
||||
nazalog.Out(nazalog.LevelDebug, 3, fmt.Sprintf("[%s] < Lock(). gid=%d", m.uniqueKey, gid))
|
||||
}
|
||||
|
||||
func (m *Mutex) Unlock() {
|
||||
m.mu.Lock()
|
||||
gid, _ := CurGoroutineID()
|
||||
if gid != m.gid {
|
||||
if m.gid == unlockedGid {
|
||||
nazalog.Out(nazalog.LevelError, 3,
|
||||
fmt.Sprintf("[%s] unlock of unlocked mutex. lock gid=%d, unlock gid=%d", m.uniqueKey, m.gid, gid))
|
||||
} else {
|
||||
nazalog.Out(nazalog.LevelError, 3,
|
||||
fmt.Sprintf("[%s] mismatched unlock. lock gid=%d, unlock gid=%d", m.uniqueKey, m.gid, gid))
|
||||
}
|
||||
}
|
||||
m.gid = unlockedGid
|
||||
m.mu.Unlock()
|
||||
|
||||
nazalog.Out(nazalog.LevelDebug, 3, fmt.Sprintf("[%s] > Unlock(). gid=%d", m.uniqueKey, gid))
|
||||
m.core.Unlock()
|
||||
nazalog.Out(nazalog.LevelDebug, 3, fmt.Sprintf("[%s] < Unlock(). gid=%d", m.uniqueKey, gid))
|
||||
}
|
Loading…
Reference in New Issue