英文:
Write to same channel with multiple goroutines
问题
这段代码能正常工作的原因是,你使用了无缓冲通道(unbuffered channel)。无缓冲通道在接收前必须有发送操作,否则发送操作会被阻塞。在你的代码中,你使用了两个不同的goroutine分别向通道发送数据,因此在发送操作完成之前,接收操作不会被阻塞。
具体来说,你的main
函数创建了一个无缓冲通道ch
,然后启动了三个goroutine:write
、write2
和read
。write
和write2
函数分别在一个无限循环中向通道ch
发送字符串数据。read
函数在一个无限循环中使用select
语句监听通道ch
的接收操作和超时操作。每次循环,它会先等待1秒钟(使用time.Sleep
函数),然后尝试从通道ch
接收数据。如果在200毫秒内没有接收到数据,就会打印"timeout"。
由于无缓冲通道的特性,发送操作和接收操作是同步的。当write
和write2
函数向通道发送数据时,它们会阻塞直到有其他goroutine准备好接收数据。因此,即使你在不同的goroutine中发送数据,由于接收操作是在read
函数中进行的,所以发送操作不会被阻塞。
需要注意的是,由于select{}
语句会一直阻塞程序的执行,你的程序会一直运行下去,除非手动停止它。
英文:
This piece of code work as properly and my question is why. Ive learnt that you can only send one value to an unbuffered channel before its blocked. But in my code i write to it two times, but from different go routines, and it works. Would appreciate if someone could explain to me why!
func main(){
var ch chan string =make(chan string)
go write(ch)
go write2(ch)
go read(ch)
select{}
}
func write(ch chan string){
for{
ch<-"write1"
}
}
func write2(ch chan string){
for{
ch<-"write2"
}
}
func read(ch chan string){
for{
time.Sleep(time.Second)
select{
case res:= <-ch: fmt.Println(res)
case <-time.After(time.Millisecond*200): fmt.Println("time out")
}
}
}
答案1
得分: 8
你可以再次写入它,因为你已经从中读取过。在读取操作之后,可以进行另一次写入。无论哪个goroutine执行写入或读取操作都没有关系。
Go内存管理页面对此进行了解释。
英文:
You can write to it again because you read from it. After read operation another write can happen. It does not really matter from which goroutine executes the write or read operation.
The Go Memory Management page explains it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论