现在主流os调用粒度为线程,产生时钟中断后,中断处理函数,如果当前线程时间片使用完毕。则切换到其他的线程,资源开销很大。还有创建和销毁线程是和很消耗线程资源的。特别是对于我们后台程序开发,为了减少不必要的性能开销,广泛采用"池"进行维护。
于是乎协程出现了,协程可以理解为用户级别线程,它的调用由线程实现,线程进行协程调用(协议可以主动让出时间片)。所以开销非常小,据统计(不知道真否,没有测试过)进程可以直接开上w的协程。其实其实这个在很久以前就提出过这个概念。现在在一些的脚本语言(比如说lua,python)已经开始支持。C语言中也有很多类似开源的协程库,(例如腾讯的协程库libco)。
go语言语言级别支持协程。使用关键字go,代码如下:
func Run(){
/*
*代码实现
*/
}
go Run()
现在启动了一个Run()协程,当然我们也给协程函数()传递参数
他同时支持对象的成员函数(),代码如下:
type Person struct{
}
func (this *Person) See(){
/*
*代码实现
*/
}
func main(){
var person Person
go person.See()
}
这样的话,我们就不需要进行所谓的“池”的维护,异步任务采用协程去做,不用担心协程开销,对被动的连接处理,直接开启协程进行IO操作。开发者心智成本大大降低。
协程的使用自然少不了协程之间通信,协程之间通信采用隧道channel,channel也是一个引用对象,通过内置函数make(),代码如下:
io_chann:=make(chan int, 1)//创建大小1,类型为int的隧道
io_chann<-1
io_chann<-2 // 隧道已经满,阻塞
这里主要说一下协程如何通信:代码如下:
func Recv(chann chan int) {
for {
<-chann // 不关心它的值
}
}
func Send(chann chan int) {
for {
chann <- 1
}
}
func main() {
chann := make(chan int, 256) // 大小256
go Recv(chann)
go Send(chann)
time.Sleep(100 * time.Second)
上面就是一个简单的协程之间通信,很简单