【问题标题】:Unobvious deadlock situation不明显的死锁情况
【发布时间】:2018-05-25 07:52:58
【问题描述】:

您能解释一下为什么会发生这种死锁吗?

package main

import (
    "sync"
    "fmt"
    "runtime"
)

func main() {
    m := sync.RWMutex{}
    go func(){
        m.RLock()
        runtime.Gosched()
        m.RLock()
        m.RUnlock()
        m.RUnlock()
    }()

    runtime.Gosched()
    m.Lock()
    m.Unlock()

    fmt.Println("works")
}

我不明白为什么这种死锁总是 大多会发生。 这可能是调度程序的怪癖吗?

【问题讨论】:

  • 这并不总是发生。你的说法没有证据。我试过了,并且能够“挤压”它打印"works" 的运行。这个问题原样似乎不是很周到。附言Go Playground 缓存输出并且不再运行代码。我在本地测试过。

标签: go synchronization


【解决方案1】:

来自 RWMutex 文档:

如果一个 goroutine 持有一个 RWMutex 用于读取,而另一个 goroutine 可能 调用 Lock,没有 goroutine 应该期望能够获得读取 锁定直到初始读锁定被释放。特别是,这 禁止递归读锁定。这是为了确保锁 最终变得可用;被阻止的 Lock 调用会排除新的读者 从获得锁。

那么当死锁发生时你的代码中发生了什么:

  1. 第一个 RLock()
  2. Lo​​ck() // 这个调用会等到第一个 Rlock() 释放并阻塞对未来 Rlocks() 的调用
  3. Rlock() // 这个调用一直等到 Lock() 被释放

【讨论】:

  • 所以这是一个写优先的 RW 锁。我说的对吗?
  • 我猜,你是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-03
  • 2019-03-15
  • 2011-10-20
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
相关资源
最近更新 更多