goroutine学习

还在学习中,理解的更为透彻了再来总结。缓存

 

goroutine和channel

无缓存channel每一个发送和接收操做的同步性,由于因为无缓冲区,因此其余goroutine的发送会被阻塞在那边,只有接收完毕后,某个goroutine才能写入这个channel。异步

有缓冲区channel会使得读写routine(或者说是收发goroutine)是异步的,只要再缓冲区没有满,其余的协程就能继续写,缓冲区不空,其余的协程就能继续读。学习

 

unbuffered channel

若是是unbuffered channel,那么发送者的goroutine会被阻塞,直到被别的goroutine接收后才会继续往下走。以下这段代码是错误的,会一直被阻塞,go run的时候报错:spa

1 func main() {
2     ch := make(chan int) //unbuffered channel
3     a := 10
4     ch <- a //blocked here
5     b := <-ch
6     fmt.Println(b)
7 }

fatal error: all goroutines are asleep - deadlock!code

goroutine 1 [chan send]协程

有两种方法修改,第一种改为buffered channel:blog

1 func main() {
2     ch := make(chan int, 1) //buffered channel
3     a := 10
4     ch <- a
5     b := <-ch
6     fmt.Println(b)
7 }  //正确输出10

第二种是将发送这个动做放在一个goroutine中,这样就不会阻塞主goroutine,主goroutine中的接收动做就得以完成:get

1 func main() {
2     ch := make(chan int) //unbuffered channel
3     a := 10
4     go func() { ch <- a }() // new a goroutine
5     b := <-ch
6     fmt.Println(b)
7 }

 ubuffered channel的发送和接收goroutine之间是同步的,不是异步的。带缓冲区的channel是异步的。同步

 channel的零值是nil,注意:若是其通道是nil,它将永远不会被选择。it

判断channel是否关闭

详见:如何优雅的关闭channel

一、若是channel已经关闭,继续往它发送数据会致使panic: send on closed channel 

二、关闭一个已经关闭的channel,会致使panic:close of closed channel 

三、读取一个已经关闭的channel,能够读出没有读完的channel。读完后会读到零值。能够屡次读取。

 1 func test(){
 2     ch:=make(chan int,3)
 3     ch<-3
 4     ch<-2
 5     ch<-1
 6     close(ch)
 7     fmt.Print(<-ch)
 8     fmt.Print(<-ch)
 9     fmt.Print(<-ch)
10     fmt.Print(<-ch)
11     fmt.Print(<-ch)
12 }
13 //right

 不能经过判断返回值是不是零值(包括nil)来判断channel是否已经关闭,应为nil能够做为值传递给channel:

1 func main() {
2     ch := make(chan interface{}, 10)
3     ch <- nil
4 
5     a := <-ch
6     fmt.Println(a)     //输出nil,没有close
7 }
相关文章
相关标签/搜索