加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

并发 – 在RWMutex解锁后两次调用RWMutex RLock时的goroutine块

发布时间:2020-12-20 11:43:23 所属栏目:Python 来源:网络整理
导读: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. 如果
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()行解决了这样的场景(花了我几个小时精确定位).

解决方法

这是读写锁的几种标准行为之一.什么 Wikipedia calls “Write-preferring RW locks”.

同步的文档RWMutex.Lock说:

To ensure that the lock eventually becomes available,a blocked Lock call excludes new readers from acquiring the lock.

否则,一系列读者在上一次发布之前就已经获得了读锁定,它可能会无限期地挨饿.

这意味着在RWMutex上调用RLock始终是不安全的,因为相同的goroutine已经读取了锁定. (顺便说一句,对常规互斥锁也是如此,因为Go的互斥锁不支持递归锁定.)

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读