• 请不要在回答技术问题时复制粘贴 AI 生成的内容
SlipStupig
V2EX  ›  程序员

求助! golang chan 同步小白问题

  •  
  •   SlipStupig · Mar 8, 2018 · 3064 views
    This topic created in 2986 days ago, the information mentioned may be changed or developed.

    本人是 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 replies    2018-03-08 19:31:30 +08:00
    VicYu
        1
    VicYu  
       Mar 8, 2018
    主线程已经执行并结束,并不会等待各个 go 的执行完成的
    SlipStupig
        2
    SlipStupig  
    OP
       Mar 8, 2018
    @VicYu 我不是加了一个 WaitGroup,按道理说已经会堵塞啊
    simple2025
        3
    simple2025  
       Mar 8, 2018
    大佬,又去学 golnag,NB
    gnenux
        4
    gnenux  
       Mar 8, 2018 via iPhone
    for i:=0;i<100;i++ {
    data<- i
    }
    KIDJourney
        5
    KIDJourney  
       Mar 8, 2018   ❤️ 1
    @SlipStupig 你的主进程可能在 Add 前就结束了,你可以加个 sleep 试一下。
    KIDJourney
        6
    KIDJourney  
       Mar 8, 2018
    @KIDJourney 忽略,看起来并不是这个原因。
    picone
        7
    picone  
       Mar 8, 2018   ❤️ 1
    有没有考虑过一个问题,在 producer 和 consumer 执行之前,已经执行到 defer waiter.Wait(),那时候 waiter 还没有 Add
    你可以把 WaitGroup.Add 放到 go routine 之前
    VicYu
        8
    VicYu  
       Mar 8, 2018   ❤️ 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
       Mar 8, 2018
    @chenqh 不努力就被淘汰了啊

    @KIDJourney 确实是这样,我现在改成在执行线程之前先 add(2),就可以了
    SlipStupig
        10
    SlipStupig  
    OP
       Mar 8, 2018
    @picone 确实是这样,go 的子线程是不堵塞的,然后 waitgroup 已经清空了不会再堵塞了
    anthow
        11
    anthow  
       Mar 8, 2018
    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  
       Mar 8, 2018
    看了下八成是 defer waiter 造成的吧,一般都是手动在最后调下 wg.Wait(),另外就是 select 如果 chan 还没数据会不断地执行 default 的语句,建议 consumer 加个 sleep 吧,进了 default 就 sleep 一下
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3300 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 52ms · UTC 00:30 · PVG 08:30 · LAX 17:30 · JFK 20:30
    ♥ Do have faith in what you're doing.