协程:本质上是一种用户态线程,不需要操作系统来进行抢占式调度,且在真正的实现重寄存于线程中,因此,系统开销极小,可以有效提高线程的任务并发性,从而避免多线程的缺点。使用协程的优点是编程简单,结构清晰;缺点是需要语言的支持。
协程最大优势:”轻量级”,可以轻松创建上百万个而不会导致系统资源衰竭,线程和进程最多不超1万个
Go语言支持协程(轻量级线程)
(1)Go语言采用消息机制作为通信方式
(2)channel是Go语言在语言级别提供的goroutine间的通信方式
(3)channel是类型相关的,也就是说一个channel只能传递一种类型的值,且channel必然是同时支持读写的
有关channel的基本语法
(1)声明:
var chanName chan ElementType
声明一个传递类型为int的channel
var ch chan int
(2)定义
ch:=make(chan int)
声明并初始化
(3)读写
读:<-ch
写:ch<-
写入:
ch<-value//向channel写入数据通常会导致程序阻塞,直到有其他goroutine从这个channel中读取数据
读取:
value:=<-ch
如果channel之前没有写入数据那么从channel中读取数据也会导致程序阻塞,知道channel中被写入数据为止
(4)带缓冲的channel
创建方式:
c:=make(chan int,1024)
//创建了一个大小为1024的int类型channel,再缓冲区没有填完前可以一直写入
读取方式:
for i:=range c{
fmt.Println(“Received:”,i)
}
(5)关闭
close(ch)
如何判断他已经关闭:
x,ok:=<-ch
只需要看第二个bool返回值就好了,如果他是false则说明已经关闭了
Go语言中的select
特点:只要其中一个case已经完成,程序就会继续往下执行,而不会考虑其他case的情况
例子:
select{
case <-chan1:
//如果成功从chan1读取数据,做相应操作
case chan2 <- 1:
//如果成功向chan2写入数据,做相应操作
default:
//如果上述操作都不成功,则进入default处理流程
}
如何利用select避免超时等待的问题
timeout:=make(chan bool,1)
go func(){
time.Sleep(1e9)//等待一秒钟
timeout <- true
}()//匿名函数
select{
case <-ch:
//从ch中读数据
case <-timeout:
//一直没有从ch中读到数据但是从timeout中读到了数据
}
未完…