为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
qq_遁去的一_1 2021-10-11 10:31:45
var mu sync.RWMutexgo 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()行解决了这样的场景(我花了几个小时来查明)。
查看完整描述

1 回答

?
catspeake

TA贡献1111条经验 获得超0个赞

这是读写锁的几种标准行为之一。什么维基百科称之为“写宁愿RW锁”

的文档sync's RWMutex.Lock说:

为确保锁最终可用,阻塞的 Lock 调用将新读者排除在获取锁之外。

否则,在前一个释放之前,每个读取锁都获得了读取锁的一系列读取器可能会无限期地使写入饥饿。

这意味着调用同一个 goroutine 已经读锁定的RLocka总是不安全的RWMutex。(顺便说一下,这也适用Lock于常规互斥锁,因为 Go 的互斥锁不支持递归锁定。)

它不安全的原因是,如果 goroutine 阻止获取第二个读锁(由于被阻塞的写入器),它将永远不会释放第一个读锁。这将导致对互斥锁的每个未来锁调用永远阻塞,导致程序的一部分或全部死锁。如果所有 goroutine 都被阻塞,Go 只会检测到死锁。


查看完整回答
反对 回复 2021-10-11
  • 1 回答
  • 0 关注
  • 232 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信