zhengdai1990
V2EX  ›  问与答

go 问题请教,想问下下面的代码为啥会导致死锁,导致的死锁如何解决

  •  
  •   zhengdai1990 · Dec 15, 2020 · 1872 views
    This topic created in 1999 days ago, the information mentioned may be changed or developed.

    package main

    import ("math/rand"; "time")

    const R = 100 // number of readers const W = 10 // number of writers

    var done chan bool

    func db(reads chan chan int, writes chan int) { state := <- writes for { select { case reply := <-reads: reply <- state case state = <-writes: } } } func main() { reads, writes, done := make(chan chan int), make(chan int), make(chan bool) go db(reads, writes) for r := 0; r < R; r++ { // create R readers go func() { reply := make(chan int) for i := 0; i < 20; i++ { reads <- reply // stops in one out of 10 cases if rand.Intn(10) == 0 {select{}} else {<- reply} time.Sleep(time.Millisecond) } }() } for w := 0; w < W; w++ { // create W writers go func() { for i := 0; i < 20; i++ { writes <- rand.Int() % 100 time.Sleep(time.Millisecond) } done <- true }() } for k := 0; k < W; k++ {<- done} // wait for writers to terminate }

    Supplement 1  ·  Dec 15, 2020
    barbery
        1
    barbery  
       Dec 15, 2020
    本来想尝试解答一下,点进来看到代码。。。
    caryqy
        2
    caryqy  
       Dec 15, 2020
    https://play.golang.org/ 代码在这里粘贴然后分享出来
    whitehack
        3
    whitehack  
       Dec 15, 2020
    本来想尝试解答一下,点进来看到代码。。。
    14v45mJPBYJW8dT7
        4
    14v45mJPBYJW8dT7  
       Dec 15, 2020
    本想复制到 IDE 里格式化一下,但因为有注释并且没换行。。。。
    zhengdai1990
        5
    zhengdai1990  
    OP
       Dec 15, 2020
    zhengdai1990
        6
    zhengdai1990  
    OP
       Dec 15, 2020
    @rimutuyuan 贴之前是有换行的……大佬看附言
    zhengdai1990
        7
    zhengdai1990  
    OP
       Dec 15, 2020
    @barbery 大佬看下附言
    zhengdai1990
        8
    zhengdai1990  
    OP
       Dec 15, 2020
    @whitehack 大佬看下附言
    zhengdai1990
        9
    zhengdai1990  
    OP
       Dec 15, 2020
    我的理解是 reply 那个 channel 是同步的,不能光发送不接收
    Nitroethane
        10
    Nitroethane  
       Dec 15, 2020
    你这写的什么鸡脖玩意儿,看了半天要吐了…… 主要问题出在第 32 行,如果生成的随机数为 0 的话,goroutine 会卡在 这个 if 语句的 select 语句里。而这会引起连锁反应:因为 reply 是无缓冲的,导致第 18 行的代码被卡住,进而第 43 行的代码也被卡住,最后所有 goroutine 全都卡住了。你可以在第 31 行 和 32 行之间加一行 log.Println("random number in reader is 0"),你就会发现,只要这一行打印出来,程序马上 deadlock 。
    虽然 channel 可以用来同步 goroutine,但是也不能这样滥用啊。好好学习下这篇文章吧 https://golang.org/ref/mem
    zhengdai1990
        11
    zhengdai1990  
    OP
       Dec 15, 2020
    @Nitroethane 老师出的作业啊,天坑
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2898 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 02:58 · PVG 10:58 · LAX 19:58 · JFK 22:58
    ♥ Do have faith in what you're doing.