【发布时间】:2015-05-30 16:16:21
【问题描述】:
我创建了两个goroutinesender和receiver,sender会不断的从用户(键盘)获取数据并写入stream,receiver会独立获取值从流中将其打印到屏幕上。两者都使用 goroutine 并发
在某个时间点,receiver 失败并关闭连接并退出receiver goroutine,但sender goroutine 等待用户输入(i/o 操作)不会被关闭。在这种情况下如何退出所有的 goroutine?
以下是此场景的示例代码。
package main
import (
"fmt"
"time"
)
var stop bool = false
func sender() {
str := ""
for !stop {
fmt.Scanf("%s", &str)
fmt.Println("Entered :", str)
}
fmt.Println("Closing sender goroutine")
}
func receiver() {
i := 0
for !stop {
i++
if i > 5 {
stop = true
}
time.Sleep(1 * time.Second)
}
fmt.Println("Closing receiver goroutine")
}
func main() {
go sender()
go receiver()
/* Wait for goroutines to finish */
for !stop {
time.Sleep(1 * time.Millisecond)
}
time.Sleep(1 * time.Second)
panic("Display stack")
}
上述代码发送方将在 5 次循环后等待用户输入接收方将退出接收方 go 例程。 I expect when receiver close, go routine which waiting on i/o has to be closed.
请帮我解答这个问题。
【问题讨论】:
-
旁注:同时读写同一个变量 (
stop) 是不安全的。不要永远这样做。这是一场经典的数据竞赛,拥有completely undefined behaviour。 Go 的race detector 可以为您指出这些。 -
在这个例子中你实际上并没有发送任何东西。但是,如果您只是想要原始数据(字符串、字节),那么可能
io.Pipe可能会方便双方执行defer myside.Close()(其中myside是管道的读取端或写入端,视情况而定) .在一般情况下,您会使用一个通道来发送数据,并且编写器可以关闭它以表示它已完成;但读者不应该/不能关闭;这通常意味着您需要一个单独的通道或其他同步机制来通知编写器退出。
标签: concurrency go goroutine