开发了一个基于key的加锁方案

kzh125 · · 4664 次点击
其实你想要的可能是这样一个东西 ```go package xsync import "sync" type lockerPerKey struct { sync.Mutex count int } type XLocker struct { locker sync.Mutex locks map[interface{}]*lockerPerKey } func NewXLocker() *XLocker { return &XLocker{ locks: map[interface{}]*lockerPerKey{}, } } func (l *XLocker) Lock(key interface{}) { l.locker.Lock() locker := l.locks[key] if locker == nil { locker = &lockerPerKey{} l.locks[key] = locker } locker.count++ l.locker.Unlock() locker.Lock() } func (l *XLocker) Unlock(key interface{}) { l.locker.Lock() locker := l.locks[key] locker.Unlock() locker.count-- if locker.count == 0 { delete(l.locks, key) } l.locker.Unlock() } ``` ``` package xsync import ( "testing" ) func BenchmarkUtil(b *testing.B) { var i = 0 u := NewUtil() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { locker, _ := u.Locker("test") locker.Lock() i++ locker.Unlock() locker.Close() } }) } func BenchmarkXsync(b *testing.B) { var i = 0 l := NewMultilocker() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { mu := l.Get("test") mu.Lock() i++ mu.Unlock() l.Put("test") } }) } func BenchmarkXLocker(b *testing.B) { var i = 0 u := NewXLocker() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { u.Lock("test") i++ u.Unlock("test") } }) } ``` ``` Running tool: /home/jarlyyn/goroot/go1.13/bin/go test -benchmem -run=^$ -bench . goos: linux goarch: amd64 BenchmarkUtil-12 4816842 215 ns/op 0 B/op 0 allocs/op BenchmarkXsync-12 1501810 821 ns/op 104 B/op 2 allocs/op BenchmarkXLocker-12 13804106 91.2 ns/op 0 B/op 0 allocs/op PASS ok _/tmp/test 4.686s ```
#19
更多评论
………… 一个sync.Map,值是sync.Mutex类型就可以了……
#1
找了下我的代码,大概是这样的 func NewUtil() *Util { return &Util{ locks: &sync.Map{}, } } type Util struct { locks *sync.Map } func (u *Util) Locker(key string) (*Locker, bool) { newlocker := &Locker{ Map: u.locks, Key: key, } v, ok := u.locks.LoadOrStore(key, newlocker) return v.(*Locker), ok } type Locker struct { sync.RWMutex Map *sync.Map Key string } func (l *Locker) Unlock() { l.RWMutex.Unlock() l.Map.Delete(l.Key) }
#2