Ⅰ. Issue Description
cleanup goroutine may delete the lock key from m.keys when the lock is not released, and then the lock is not exclusive.
Ⅱ. Describe what happened
goroutine 2 could acquire the lock when goroutine 1 is holding the lock.
Ⅲ. Describe what you expected to happen
goroutine 2 should be blocked until goroutine 1 release the lock.
Ⅳ. How to reproduce it (as minimally and precisely as possible)
func TestKMutexClean(t *testing.T) {
m := New()
var resource atomic.Int32
c2 := make(chan struct{})
done := make(chan struct{})
go func() {
time.Sleep(57 * time.Second)
m.Lock("key")
defer m.Unlock("key")
if !resource.CompareAndSwap(0, 1) {
panic("init error")
}
time.Sleep(4 * time.Second)
close(c2)
time.Sleep(1 * time.Second)
if !resource.CompareAndSwap(1, 0) {
panic("lock is not exclusive")
}
}()
go func() {
<-c2
m.Lock("key")
defer m.Unlock("key")
if !resource.CompareAndSwap(0, 2) {
panic("resource is used by other")
}
close(done)
}()
<-done
}
Ⅰ. Issue Description
cleanup goroutine may delete the lock key from
m.keyswhen the lock is not released, and then the lock is not exclusive.Ⅱ. Describe what happened
goroutine 2 could acquire the lock when goroutine 1 is holding the lock.
Ⅲ. Describe what you expected to happen
goroutine 2 should be blocked until goroutine 1 release the lock.
Ⅳ. How to reproduce it (as minimally and precisely as possible)