gpt4 book ai didi

multithreading - 如何在 Golang 的 goroutines 中安全地与 channel 交互

转载 作者:IT王子 更新时间:2023-10-29 01:34:47 26 4
gpt4 key购买 nike

我是新手,我正在尝试了解 goroutine 中 channel 的工作方式。据我了解,关键字 range 可用于迭代 channel 的值,直到 channel 关闭或缓冲区用完;因此,for range c 将重复循环,直到缓冲区用完。

我有以下简单的功能可以为 channel 增加值(value):

func main() {

c := make(chan int)
go printchannel(c)
for i:=0; i<10 ; i++ {
c <- i
}

}

我有两个 printchannel 的实现,我不确定行为为何不同。

实现 1:

func printchannel(c chan int) {
for range c {
fmt.Println(<-c)
}
}

输出:1 3 5 7

实现 2:

func printchannel(c chan int) {
for i:=range c {
fmt.Println(i)
}
}

输出:0 1 2 3 4 5 6 7 8

我没想到这些输出!

想要的输出:0 1 2 3 4 5 6 7 8 9

main 函数和 printchannel 函数是否应该在两个线程上并行运行,一个向 channel 添加值,另一个读取值直到 channel 关闭?我可能在这里遗漏了一些基本的 go/thread 概念,指向它的指针会很有帮助。

非常感谢对此的反馈(以及我对 goroutine 中 channel 操作的理解)!

最佳答案

实现 1. 您正在从 channel 读取两次 - range c<-c都在从 channel 中读取。

实现 2. 这是正确的方法。您可能看不到 9 的原因是两个 goroutine 可能在并行线程中运行。在那种情况下,它可能是这样的:

  1. main goroutine 将 9 发送到 channel 并阻塞,直到它被读取
  2. 第二个 goroutine 从 channel 接收 9
  3. main goroutine 解除阻塞并退出。这终止了整个程序,它不给第二个 goroutine 机会打印 9

在这种情况下,您必须同步您的 goroutine。比如像这样

func printchannel(c chan int, wg *sync.WaitGroup) {
for i:=range c {
fmt.Println(i)
}

wg.Done() //notify that we're done here
}

func main() {
c := make(chan int)
wg := sync.WaitGroup{}

wg.Add(1) //increase by one to wait for one goroutine to finish
//very important to do it here and not in the goroutine
//otherwise you get race condition

go printchannel(c, &wg) //very important to pass wg by reference
//sync.WaitGroup is a structure, passing it
//by value would produce incorrect results

for i:=0; i<10 ; i++ {
c <- i
}

close(c) //close the channel to terminate the range loop
wg.Wait() //wait for the goroutine to finish
}

至于协程与线程。你不应该混淆它们并且可能应该理解它们之间的区别。 Goroutines 是绿色线程。关于该主题的博客文章、讲座和 stackoverflow 答案数不胜数。

关于multithreading - 如何在 Golang 的 goroutines 中安全地与 channel 交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49971237/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com