This package implements Mutex
and RWMutex
. They are similar to sync.Mutex
and sync.RWMutex
, but
they track which goroutine locked the mutex and will not cause a deadlock if
the same goroutine will try to lock the same mutex again.
type myEntity struct {
gorex.Mutex
}
func (ent *myEntity) func1() {
ent.Lock()
defer ent.Unlock()
.. some stuff ..
ent.func2() // will not get a deadlock here!
.. other stuff ..
}
func (ent *myEntity) func2() {
ent.Lock()
defer ent.Unlock()
.. more stuff ..
}
The same in other syntax:
type myEntity struct {
gorex.Mutex
}
func (ent *myEntity) func1() {
ent.LockDo(func() {
.. some stuff ..
ent.func2() // will not get a deadlock here!
.. other stuff ..
})
}
func (ent *myEntity) func2() {
ent.LockDo(func(){
.. more stuff ..
})
}
locker := &goroutine.RWMutex{}
locker.RLockDo(func() {
.. do some read-only stuff ..
if cond {
return
}
locker.LockDo(func() { // will not get a deadlock here!
.. do write stuff ..
})
})
But you still will get a deadlock if you do this way:
var locker = &gorex.RWMutex{}
func someFunc() {
locker.RLockDo(func() {
.. do some read-only stuff ..
if cond {
return
}
locker.LockDo(func() { // you will get a deadlock here!
.. do write stuff ..
})
})
}()
func main() {
go someFunc()
go someFunc()
}
because there could be a situation that a resource is blocked by a RLockDo
from
both goroutines and both goroutines waits (on LockDo
) until other goroutine
will finish RLockDo
. But still you will easily see the reason of deadlocks due
to LockDo
-s in the call stack trace.
It's essentially slower than bare sync.Mutex
/sync.RWMutex
:
goos: linux
goarch: amd64
pkg: github.com/xaionaro-go/gorex
Benchmark/Lock-Unlock/single/sync.Mutex-8 77933413 15.2 ns/op 0 B/op 0 allocs/op
Benchmark/Lock-Unlock/single/sync.RWMutex-8 46052574 26.1 ns/op 0 B/op 0 allocs/op
Benchmark/Lock-Unlock/single/Mutex-8 20281420 58.6 ns/op 0 B/op 0 allocs/op
Benchmark/Lock-Unlock/single/RWMutex-8 13518639 87.1 ns/op 0 B/op 0 allocs/op
Benchmark/Lock-Unlock/parallel/sync.Mutex-8 10836991 111 ns/op 0 B/op 0 allocs/op
Benchmark/Lock-Unlock/parallel/sync.RWMutex-8 9065725 133 ns/op 0 B/op 0 allocs/op
Benchmark/Lock-Unlock/parallel/Mutex-8 9425310 123 ns/op 2 B/op 0 allocs/op
Benchmark/Lock-Unlock/parallel/RWMutex-8 5309696 213 ns/op 4 B/op 0 allocs/op
Benchmark/RLock-RUnlock/single/sync.RWMutex-8 76609815 15.2 ns/op 0 B/op 0 allocs/op
Benchmark/RLock-RUnlock/single/RWMutex-8 25071478 47.9 ns/op 0 B/op 0 allocs/op
Benchmark/RLock-RUnlock/parallel/sync.RWMutex-8 25705654 48.3 ns/op 0 B/op 0 allocs/op
Benchmark/RLock-RUnlock/parallel/RWMutex-8 14786738 80.9 ns/op 0 B/op 0 allocs/op
Benchmark/Lock-ed:Lock-Unlock/single/Mutex-8 31392260 38.2 ns/op 0 B/op 0 allocs/op
Benchmark/Lock-ed:Lock-Unlock/single/RWMutex-8 32588916 37.6 ns/op 0 B/op 0 allocs/op
Benchmark/RLock-ed:RLock-RUnlock/single/RWMutex-8 26416754 46.1 ns/op 0 B/op 0 allocs/op
Benchmark/RLock-ed:RLock-RUnlock/parallel/RWMutex-8 13113901 88.7 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/xaionaro-go/