Ory*_*and 4 concurrency mutex go
var mu sync.RWMutex
go func() {
mu.RLock()
defer mu.RUnlock()
mu.RLock() // In my real scenario this second lock happened in a nested function.
defer mu.RUnlock()
// More code.
}()
mu.Lock()
mu.Unlock() // The goroutine above still hangs.
Run Code Online (Sandbox Code Playgroud)
如果一个函数读锁定读/写互斥的两倍,而另一个函数写锁,然后直写未锁相同的互斥体,原有的功能仍然挂起.
这是为什么?是因为有一个连续顺序,互斥量允许代码执行?
我刚刚通过删除第二mu.RLock()行解决了这样的情况(花了我几个小时精确定位).
这是读写锁的几种标准行为之一.什么维基百科称之为"写宁愿RW锁".
文档sync's RWMutex.Lock说:
为确保锁定最终可用,阻止的锁定调用会阻止新读取者获取锁定.
否则,一系列读者在上一次发布之前就已经获得了读锁定,它可能会无限期地挨饿.
这意味着,它始终是不安全的调用RLock上RWMutex,同样够程已经读过锁定.(顺便说一下,Lock对于常规互斥锁也是如此,因为Go的互斥锁不支持递归锁定.)
它是不安全的原因是,如果goroutine阻止获得第二次读锁(由于被阻止的写入器),它将永远不会释放第一个读锁定.这将导致互斥锁上的每个未来锁定调用永远阻塞,解锁部分或全部程序.如果所有goroutine都被阻止,Go将仅检测到死锁.