V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
SlipStupig
V2EX  ›  程序员

求助! golang chan 同步小白问题

  •  
  •   SlipStupig · 2018-03-08 14:28:53 +08:00 · 2458 次点击
    这是一个创建于 2486 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本人是 golang 小白, 写一段代码, 通过go coroutine同时启动生产者消费者,然后生产者没产生任何数据,消费者也没接收到任何数据,然后主线程就退出了

    • 伪代码如下
    
    var waiter sync.WaitGroup
    
    func producer(data chan interface{}){
        waiter.Add(1)
       defer func(){
        waiter.Done()
         close(data)
    }()
    // start sending
        for i:=0 ; i > 100; i++{
            data <- i
    }
    }
    
    func consumer(data chan interface{}){
        waiter.Add(1)
       defer waiter.Done()
      end:
        for {
           select {
          case item, Ok:= <- data:
              if !Ok{
                  break end:
             }else {
                  // do something
    
             }
    default:
        continue
    }
    }
    }
    func main(){
    
    defer waiter.Wait()
    pipe := make(chan interface{})
    go producer(pipe)
    go consumer(pipe)
    
    }
    

    希望各位高手能指出我的错误 😱

    12 条回复    2018-03-08 19:31:30 +08:00
    VicYu
        1
    VicYu  
       2018-03-08 14:32:49 +08:00
    主线程已经执行并结束,并不会等待各个 go 的执行完成的
    SlipStupig
        2
    SlipStupig  
    OP
       2018-03-08 14:39:08 +08:00
    @VicYu 我不是加了一个 WaitGroup,按道理说已经会堵塞啊
    chenqh
        3
    chenqh  
       2018-03-08 14:44:37 +08:00
    大佬,又去学 golnag,NB
    gnenux
        4
    gnenux  
       2018-03-08 14:46:41 +08:00 via iPhone
    for i:=0;i<100;i++ {
    data<- i
    }
    KIDJourney
        5
    KIDJourney  
       2018-03-08 14:47:21 +08:00   ❤️ 1
    @SlipStupig 你的主进程可能在 Add 前就结束了,你可以加个 sleep 试一下。
    KIDJourney
        6
    KIDJourney  
       2018-03-08 14:49:58 +08:00
    @KIDJourney 忽略,看起来并不是这个原因。
    picone
        7
    picone  
       2018-03-08 14:52:42 +08:00   ❤️ 1
    有没有考虑过一个问题,在 producer 和 consumer 执行之前,已经执行到 defer waiter.Wait(),那时候 waiter 还没有 Add
    你可以把 WaitGroup.Add 放到 go routine 之前
    VicYu
        8
    VicYu  
       2018-03-08 14:59:15 +08:00   ❤️ 1
    ```golang
    package main

    import (
    "fmt"
    "sync"
    )

    var wg sync.WaitGroup

    func test(i int) {
    fmt.Println(i)
    wg.Done()
    }
    func testAdd() {
    wg.Add(1)
    }

    func main() {
    defer wg.Wait()
    for i:= 0; i < 10; i++ {
    go testAdd()
    go test(i)
    }
    }
    ```

    你跑上面这个,多跑几次
    SlipStupig
        9
    SlipStupig  
    OP
       2018-03-08 15:00:46 +08:00
    @chenqh 不努力就被淘汰了啊

    @KIDJourney 确实是这样,我现在改成在执行线程之前先 add(2),就可以了
    SlipStupig
        10
    SlipStupig  
    OP
       2018-03-08 15:10:07 +08:00
    @picone 确实是这样,go 的子线程是不堵塞的,然后 waitgroup 已经清空了不会再堵塞了
    anthow
        11
    anthow  
       2018-03-08 17:23:02 +08:00
    The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished.
    xwhxbg
        12
    xwhxbg  
       2018-03-08 19:31:30 +08:00
    看了下八成是 defer waiter 造成的吧,一般都是手动在最后调下 wg.Wait(),另外就是 select 如果 chan 还没数据会不断地执行 default 的语句,建议 consumer 加个 sleep 吧,进了 default 就 sleep 一下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2770 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 03:49 · PVG 11:49 · LAX 19:49 · JFK 22:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.