使用多个goroutine向同一通道写入数据。

huangapple go评论90阅读模式
英文:

Write to same channel with multiple goroutines

问题

这段代码能正常工作的原因是,你使用了无缓冲通道(unbuffered channel)。无缓冲通道在接收前必须有发送操作,否则发送操作会被阻塞。在你的代码中,你使用了两个不同的goroutine分别向通道发送数据,因此在发送操作完成之前,接收操作不会被阻塞。

具体来说,你的main函数创建了一个无缓冲通道ch,然后启动了三个goroutine:writewrite2readwritewrite2函数分别在一个无限循环中向通道ch发送字符串数据。read函数在一个无限循环中使用select语句监听通道ch的接收操作和超时操作。每次循环,它会先等待1秒钟(使用time.Sleep函数),然后尝试从通道ch接收数据。如果在200毫秒内没有接收到数据,就会打印"timeout"。

由于无缓冲通道的特性,发送操作和接收操作是同步的。当writewrite2函数向通道发送数据时,它们会阻塞直到有其他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.

huangapple
  • 本文由 发表于 2015年3月30日 17:30:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/29342701.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定