V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
zhengdai1990
V2EX  ›  问与答

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

  •  
  •   zhengdai1990 · 2020-12-15 15:30:21 +08:00 · 1074 次点击
    这是一个创建于 1440 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 }

    第 1 条附言  ·  2020-12-15 16:07:29 +08:00
    barbery
        1
    barbery  
       2020-12-15 15:40:44 +08:00
    本来想尝试解答一下,点进来看到代码。。。
    caryqy
        2
    caryqy  
       2020-12-15 15:42:41 +08:00
    https://play.golang.org/ 代码在这里粘贴然后分享出来
    whitehack
        3
    whitehack  
       2020-12-15 15:44:33 +08:00
    本来想尝试解答一下,点进来看到代码。。。
    rimutuyuan
        4
    rimutuyuan  
       2020-12-15 15:44:50 +08:00
    本想复制到 IDE 里格式化一下,但因为有注释并且没换行。。。。
    zhengdai1990
        5
    zhengdai1990  
    OP
       2020-12-15 16:07:41 +08:00
    zhengdai1990
        6
    zhengdai1990  
    OP
       2020-12-15 16:08:04 +08:00
    @rimutuyuan 贴之前是有换行的……大佬看附言
    zhengdai1990
        7
    zhengdai1990  
    OP
       2020-12-15 16:08:15 +08:00
    @barbery 大佬看下附言
    zhengdai1990
        8
    zhengdai1990  
    OP
       2020-12-15 16:08:42 +08:00
    @whitehack 大佬看下附言
    zhengdai1990
        9
    zhengdai1990  
    OP
       2020-12-15 16:09:36 +08:00
    我的理解是 reply 那个 channel 是同步的,不能光发送不接收
    Nitroethane
        10
    Nitroethane  
       2020-12-15 17:18:19 +08:00
    你这写的什么鸡脖玩意儿,看了半天要吐了…… 主要问题出在第 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
       2020-12-15 22:50:07 +08:00
    @Nitroethane 老师出的作业啊,天坑
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2731 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 11:14 · PVG 19:14 · LAX 03:14 · JFK 06:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.