两个协程用channel来传递数据时,就比如生产者消费者模型,这个channel关闭或者说协程什么时候推出循环

786789256 · 2018-06-12 08:21:49 · 1067 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2018-06-12 08:21:49 的主题,其中的信息可能已经有所发展或是发生改变。

弄了一个类似生产者消费者模型,两个协程有一个通道A,不停写入数据,B不停读取数据,因为都是for循环的,是在A里面没有数据的时候关闭Chanel、,还是在B中判断没有数据,超时就退出for循环呢? loop: for{ select { case bb,err := <-addChan: if err == false { break loop } addSlice = append(addSlice,bb) } } 代码类似这样的,但现在出现了协程死锁了,貌似是这里一直在<-addChan读取数据导致的等待超时,死锁了,但有对err判断啊,这里难道不会退出for循环么?谢谢了


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1067 次点击  
加入收藏 微博
4 回复  |  直到 2018-06-13 16:28:19
jdxj
jdxj · #1 · 7年之前

if err == false { break loop } 这句貌似永远不会执行。

  1. 我不知道还有没有其他case语句了,如果没有的话,也就是说只有那一个case的时,当该case无法从addChan读取到数据时,整个 select 是阻塞的。err是没有被赋值的。
  2. B 能读取到值时,err 肯定是 true 了。
  3. 一般是在产生数据的地方关闭channel。
lizzz49
lizzz49 · #2 · 7年之前
  1. 一般是在生产的地方关闭chanel;
  2. 在消费的地方判断从Chanel中取出的数据是不是空值或者判断chan是否关闭,如果是空值或关闭跳出循环(PS:如果是允许写入Chanel的数据是空值,或者无法确定写入数据是否有空值的,最牢靠的方式还是判断chan是否关闭)
    loop:
     for {
         select {
         case bb, isClosed := <-addChan:
             if isClosed {
                 break loop
             }
             addSlice = append(addSlice, bb)
         }
     }
    

可以看一下同步chan和缓冲chan的相关知识

lizzz49
lizzz49 · #3 · 7年之前

if 后面少了个 !

fwhez
fwhez · #4 · 7年之前

生产消费模型的生产者和消费者,可以不用退出循环 非要设计一个开关,也可以 select { case <-close: goto l } l: return

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传