当前位置: > > > > 为什么这里有通道的可变输出
为什么这里有通道的可变输出
来源:stackoverflow
2024-04-26 20:54:36
0浏览
收藏
来到米云的大家,相信都是编程学习爱好者,希望在这里学习Golang相关编程知识。下面本篇文章就来带大家聊聊《为什么这里有通道的可变输出》,介绍一下,希望对大家的知识积累有所帮助,助力实战开发!
问题内容
我正在尝试从这里修改代码。我创建 5 个通道并发送数据 5 次:
package main
import "fmt"
func greet(c chan string) {
fmt.println("hello " + <-c + "!")
}
func main() {
fmt.println("main() started")
c := make(chan string)
for i:=0; i<5; i++ {
go greet(c)
}
c <- "aaa"
c <- "bbb"
c <- "ccc"
c <- "ddd"
c <- "eee"
fmt.println("main() stopped")
}
我希望打印所有 5 个字符串。但是,我发现输出可变。一些输出是:
$ ./rnchannel main() started Hello AAA! Hello DDD! Hello BBB! Hello CCC! Hello EEE! main() stopped $ ./rnchannel main() started Hello CCC! Hello DDD! main() stopped $ ./rnchannel main() started Hello CCC! Hello BBB! Hello AAA! Hello DDD! main() stopped
为什么打印的行数可变?
解决方案
。当 main() 退出时,所有 goroutine 都会被杀死。无法保证您的其他 goroutine 会在此之前完成,这就是并发的本质。以下是修复方法。
首先,让我们对 greet 进行一些更改。让其休眠一会儿,以使问题更加明显。我们还将让它接受字符串而不是通道,稍后我们就会明白原因。
func greet(str string) {
time.sleep(100 * time.millisecond)
fmt.println("hello " + str + "!")
}
我们不需要创建一堆 goroutine 从通道读取固定次数的数据,而是需要一个 goroutine 从通道读取数据直到耗尽。使用 最容易完成此操作。这充分利用了渠道。
我们还需要一种方法来告诉主程序等待循环完成。 。更复杂的同步使用。
c := make(chan string, 2)
done := make(chan bool, 1)
go func() {
for str := range(c) {
greet(str)
}
done <- true
}()
goroutine 将从 c 读取数据,直到它关闭。然后它将发送 true 到通道 done。两者都经过缓冲,以避免由于阻塞等待读取或写入通道而导致死锁。
回到main,我们写入通道,显式关闭它,然后等待从done读取。
c <- "aaa"
c <- "bbb"
c <- "ccc"
c <- "ddd"
c <- "eee"
close(c)
<-done
fmt.println("main() stopped")
<-done 将阻塞,直到有东西可读。这使得 goroutine 能够完成。
并将它们整合在一起。
package main
import(
"fmt"
"time"
)
func greet(str string) {
time.Sleep(100 * time.Millisecond)
fmt.Println("Hello " + str + "!")
}
func main() {
fmt.Println("main() started")
c := make(chan string, 2)
done := make(chan bool, 1)
go func() {
for str := range(c) {
greet(str)
}
done <- true
}()
c <- "AAA"
c <- "BBB"
c <- "CCC"
c <- "DDD"
c <- "EEE"
close(c)
<-done
fmt.Println("main() stopped")
}
您不会等到所有字符串都打印完才退出。一旦主线程到达执行结束,它就会关闭所有 goroutine 并结束程序。由于这种情况同时发生,因此无法确定将允许打印多少个字符串。
理论要掌握,实操不能落!以上关于《为什么这里有通道的可变输出》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注米云公众号吧!
