github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/sys/syncx/rwmutex.go (about) 1 package syncx 2 3 import ( 4 "runtime" 5 "sync" 6 "unsafe" 7 8 "github.com/songzhibin97/go-baseutils/internal/runtimex" 9 "github.com/songzhibin97/go-baseutils/sys/cpu" 10 ) 11 12 const ( 13 cacheLineSize = unsafe.Sizeof(cpu.CacheLinePad{}) 14 ) 15 16 var ( 17 shardsLen int 18 ) 19 20 // RWMutex is a p-shard mutex, which has better performance when there's much more read than write. 21 type RWMutex []rwMutexShard 22 23 type rwMutexShard struct { 24 sync.RWMutex 25 _pad [cacheLineSize - unsafe.Sizeof(sync.RWMutex{})]byte 26 } 27 28 func init() { 29 shardsLen = runtime.GOMAXPROCS(0) 30 } 31 32 // NewRWMutex creates a new RWMutex. 33 func NewRWMutex() RWMutex { 34 return make([]rwMutexShard, shardsLen) 35 } 36 37 func (m RWMutex) Lock() { 38 for shard := range m { 39 m[shard].Lock() 40 } 41 } 42 43 func (m RWMutex) Unlock() { 44 for shard := range m { 45 m[shard].Unlock() 46 } 47 } 48 49 func (m RWMutex) RLocker() sync.Locker { 50 return m[runtimex.Pid()%shardsLen].RWMutex.RLocker() 51 }