dplase3140 2015-04-14 18:18
浏览 33
已采纳

高朗的生产者消费者

Tried running the below code(producer & consumer) to understand goroutines and channel in golang (removed package and imports from the code snippet below):

var done = make(chan bool)
var msgs = make(chan int)

func produce() {
    for i := 0; i < 10; i++ {
            msgs <- i
    }
    fmt.Println("Before closing channel")
    close(msgs)
    fmt.Println("Before passing true to done")
    done <- true
}

func consume() {
    for {
            msg := <-msgs
            time.Sleep(100 * time.Millisecond)
            fmt.Println("Consumer: ", msg)
    }
}

func main() {
    go produce()
    go consume()
    <-done
    fmt.Println("After calling DONE")
}

source code from: http://www.golangpatterns.info/concurrency/producer-consumer

Below is the output when I run the code

Consumer:  0
Consumer:  1
Consumer:  2
Consumer:  3
Consumer:  4
Consumer:  5
Consumer:  6
Consumer:  7
Consumer:  8
Before closing channel
Before passing true to done
After calling DONE

Based on my understanding with goroutines and channel: When we call produce() and consume() from main() using the go keyword, go runtime kicks of 2 goroutines(sort of threads in java world but not actual OS threads) and the main() goroutine comes and halts at "<-done". Now inside produce() - the loop goes from 0 to 9 and inside the loop the msgs channel receives the int (0 to 9) 1 at a time which is being consumed in parallel by the consume(); however produce has no clue about it and it just keep looping for 0 to 9.

Question: Assuming my above understanding is correct. Once, the for loop is done why is the next printLine inside produce() not getting printed and also why is the msgs channel not getting closed? Why is the goroutine halting inside the produce() until the consumer consumes all the msgs?

  • 写回答

1条回答 默认 最新

  • douningle7944 2015-04-14 18:44
    关注

    The msgs channel is unbuffered. This means that for send to complete, there has to be a corresponding receive operation that can also complete. This provides a synchronization point between goroutines.

    It's easy to see if you just add a few more print statements to your example

    http://play.golang.org/p/diYQGN-iwE

    func produce() {
        for i := 0; i < 4; i++ {
            fmt.Println("sending")
            msgs <- i
            fmt.Println("sent")
        }
        fmt.Println("Before closing channel")
        close(msgs)
        fmt.Println("Before passing true to done")
        done <- true
    }
    
    func consume() {
        for msg := range msgs {
            fmt.Println("Consumer: ", msg)
            time.Sleep(100 * time.Millisecond)
    
        }
    }
    

    Output:

    sending
    Consumer:  0
    sent
    sending
    Consumer:  1
    sent
    sending
    Consumer:  2
    sent
    sending
    Consumer:  3
    sent
    Before closing channel
    Before passing true to done
    After calling DONE
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 目详情-五一模拟赛详情页
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b