美文网首页
Golang系列1之deadlock

Golang系列1之deadlock

作者: 余滴滴 | 来源:发表于2018-09-04 21:30 被阅读0次

    因为公司安排,我临时从Java项目组调往Go项目组,经过差不多5天业余时间对Go学习后,架构师让我给公司同事进行了Golang的分享和培训.
    同事们很热爱技术, 本来预计40分钟的分享, 由于同事们积极的讨论和Go大佬同事的热情补充分享, 最终持续了2个多小时. 我把此次分享中几个讨论热烈的重要知识点记录下来, 方便大家入门GO的时候避坑.

    go中的dealock主要分为两类:

    1. channel相关的死锁

    读写nil channel,导致的死锁

    func main() {
        ch := make(chan int) // block forerver
        ch <- 1  
    }
    // 如果向一个为空值(nil)的channel写入或者读取数据,当前goroutine将永远阻塞。
    func main() {
        var ch chan int
        ch <- 1   // block forerver
    }
    func main() {
        var ch chan int
        <-ch   // block forerver
    }
    func main() {
        <-chan int(nil)   // block forerver
    }
    func main() {
        chan int(nil)<-1   // block forerver
    }
    

    goroutine 1 [chan send]:

    image.png

    2. 教科书式的死锁

    互相等待对方释放锁导致的死锁,也就是操作系统教科书中的死锁.

    var lock1 *sync.Mutex
    var lock2 *sync.Mutex
    func main() {
        lock1 = new(sync.Mutex)
        lock2 = new(sync.Mutex)
        go func() {
            lock1.Lock()
            fmt.Println("I'm a goroutine,I have lock1,and I need lock2.")
            time.Sleep(time.Second)
            lock2.Lock()
            lock2.Unlock()
            lock1.Unlock()
        }()
        lock2.Lock()
        fmt.Println("I'm the main goroutine,I have lock2,and I need lock1.")
        time.Sleep(time.Second)
        lock1.Lock()
        lock1.Unlock()
        lock2.Unlock()
        time.Sleep(5 * time.Second)
    }
    

    goroutine 1 [semacquire]:

    image.png

    易错点

    Q: 是不是只要唯一的mian goroutine阻塞了,就会导致死锁
    A: 不是,只有读写nil channel导致的阻塞,才会导致死锁. 由于其他原因导致的阻塞不会导致死锁,如下面这个例子.

    func main() {
        log.Fatal(http.ListenAndServe(":8000", nil))  //block
        log.Print("This doesn't print")
        fmt.Println("Can't reach here.")
    }
    

    Q: 什么时候go的runtime会检索到deadlock // 附录3
    Currently Go only detects when the program as a whole freezes, not when a subset of goroutines get stuck.
    A: 只有当所有的goroutine都不能被访问时候, go的runtime会检测到这种情况,并抛出deadlock. (TODO,这个结论还是不太完善)

    更多deadlock的例子: https://gitee.com/sicnu-yudidi/go/tree/master/go-3/deadlock

    1. https://programming.guide/go/detect-deadlock.html
    2. https://stackoverflow.com/questions/42432880/why-does-this-goroutine-block
    3. How to debug deadlocks

    相关文章

      网友评论

          本文标题:Golang系列1之deadlock

          本文链接:https://www.haomeiwen.com/subject/fbxvwftx.html