猿问

goroutine 在 RWMutex Unlock 后调用 RWMutex RLock 两次时阻塞

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.

如果一个函数读锁定读/写互斥的两倍,而另一个函数写锁,然后直写未锁相同的互斥体,原有的功能仍然挂起。


这是为什么?是不是因为互斥体允许代码执行有一个串行顺序?


我刚刚通过删除第二mu.RLock()行解决了这样的场景(我花了几个小时来查明)。


qq_遁去的一_1
浏览 233回答 1
1回答

catspeake

这是读写锁的几种标准行为之一。什么维基百科称之为“写宁愿RW锁”。的文档sync's RWMutex.Lock说:为确保锁最终可用,阻塞的 Lock 调用将新读者排除在获取锁之外。否则,在前一个释放之前,每个读取锁都获得了读取锁的一系列读取器可能会无限期地使写入饥饿。这意味着调用同一个 goroutine 已经读锁定的RLocka总是不安全的RWMutex。(顺便说一下,这也适用Lock于常规互斥锁,因为 Go 的互斥锁不支持递归锁定。)它不安全的原因是,如果 goroutine 阻止获取第二个读锁(由于被阻塞的写入器),它将永远不会释放第一个读锁。这将导致对互斥锁的每个未来锁调用永远阻塞,导致程序的一部分或全部死锁。如果所有 goroutine 都被阻塞,Go 只会检测到死锁。
随时随地看视频慕课网APP

相关分类

Go
我要回答