Go语言并发编程_Channel

channel的简介

Go语言的并发模型实CSP(Communicating Sequential Processes)提倡通过通信共享内存而不是通过共享内存实现通信。

虽然可以使用共享内存进行数据交换,但是共享内存在不同的goroutine中容易发生竞态问题。为了保证数据交换的正确性,必须使用互斥量对内存进行加锁,这种做法势必造成性能问题。

  • channel:就是Go语言中,将一个goroutine发送特定值到另一个goroutine的通信机制。
    Go 语言中的通道(channel)是一种特殊的类型。通道就是一个队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。

channel的使用

channel的类型

  • channel是一种引用类型,声明通道的格式如下:
var 变量 chan 元素类型
-------------------------
    var ch1 chan int   // 声明一个传递整型的通道
    var ch2 chan bool  // 声明一个传递布尔型的通道
    var ch3 chan []int // 声明一个传递int切片的通道

创建channel

由于通道是引用类型,通道的值默认为nil

	var ch1 chan int
	fmt.Println(ch1)//<nil>

声明通道后需要使用make函数初始化才能使用。
make初始化通道的语法为:

    make(chan 元素类型, [缓冲大小])

操作channel

channel有三种操作:发送,接收,关闭
其中发送和接收都是使用的:<-

	ch1 := make(chan int)
	ch1 <- 10//将10发送到ch1中
	x :=<-ch1 //从ch1接收值并赋给x

关闭:

close(ch1)

注意:关闭通道并不是必须的,只有在通知接收方goroutine所有的数据都发送完毕的时候才需要关闭通道,通道可以被垃圾回收。
对一个已经关闭的通道进行发送值或者是关闭操作会导致panic。
对一个关闭的通道进行接收值可以一直取到值,直到通道为空,当通道都没有值了,再取值取得的只能是对应类型的零值。

无缓冲通道

在这里插入图片描述
无缓冲通道又称作阻塞通道:

	ch1 := make(chan int)
	ch1 <- 10//将10发送到ch1中

通过ch1 := make(chan int)创建的就是无缓冲通道,无缓冲通道只有接收方存在时才能发送值,否则就将出现死锁错误。

fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()

有两种解决方法:

  1. 启动一个goroutine去接收
func recvdata(c chan int)  {
    
    
	data :=<-c
	fmt.Println("接收成功data",data)
}
func main() {
    
    
	//var ch1 chan int
	//fmt.Println(ch1)
	ch1 := make(chan int)
	go recvdata(ch1)//启动goroutine接收通道里面的值
	ch1<-10//发送10
	fmt.Println("发送成功")
}

同步通道:无缓冲通道上的发送操作会阻塞,直到另一个goroutine在该通道上执行接收操作,这时值才能发送成功,两个goroutine将继续执行。相反,如果接收操作先执行,接收方的goroutine将阻塞,直到另一个goroutine在该通道上发送一个值。
使用无缓冲通道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也被称为同步通道。

有缓冲通道

有缓冲通道也是解决无缓冲通道存在问题的解决方案
在这里插入图片描述
只要通道的容量大于零,那么该通道就是有缓冲的通道,通道的容量表示通道中能存放元素的数量。
创建有缓冲通道:

  ch := make(chan int, 1) // 创建一个容量为1的有缓冲区通道

这样也不会出现deadlock情况。而这个数据也就存在于这个通道,进行缓冲。

单向通道

Go语言中提供了单向通道,限制数据只能发送或者接收

  1.chan<- int是一个只能发送的通道,可以发送但是不能接收;
  out chan <-int
  2.<-chan int是一个只能接收的通道,可以接收但是不能发送。
  in <-chan int

双向通道可以转变为单向,但是单向通道却不能变为双向。

猜你喜欢

转载自blog.csdn.net/H1517043456/article/details/112986275