Goroutine
golang引入了goroutine概念,它使得并发编程非常简单,一个gouroutine才4k大小。通过使用gouroutine,而不是操作系统的并发机制,以及使用消息传递来共享内存而不是使用共享内存来通信,golang让并发变得更加轻盈和安全。
通过在函数前使用关键字go,我们即可让该函数以goroutine的方式执行。goroutine是一种比线程更加轻盈,更省资源的协程。golang通过系统的线程来多路派遣这些函数的执行,使得每个使用go关键字执行的函数可以运行成为一个单位协程。当一个携程阻塞,即block的时候,调度器就会自动把其他携程安排到另外的线程中去,从而实现了程序无等待并行化的运行。而且调度器的开销非常小,一颗CPU调度的规模下于每秒百万次,这是的我们能够创建大量的gouroutine,从而可以轻松的编写高并发程序,达到我们想要的目的。
golang实现了CSP(通信顺序进程,Communicating Sequential Process)模型来作为goroutine间的推荐通信方式。在CSP模型中,一个并发系统由若干并行运行的顺序进程组成,每个进程不能对其他进程的变量进行赋值。进程之间只能通过一对通信原语实现协作。golang用channel这个概念来轻巧的实现CSP模型,channel的使用方式笔记哦啊接近UNIX系统的pip(管道)的概念,可以方便的进行跨goroutine的通信。
另外,由于一个进程内创建的所有goroutine运行在同一个内存地址空间中,因此如果不同的goroutine不得不去访问共享的内存变量,访问前应该先获取相应的读写锁。golang标准库的sync包提供了完备的读写锁功能。
下面我们使用一个简单的例子来演示goroutine和channel的使用方式。这是一个并行计算的例子,由2个goroutine进行并行的累加计算,待2个goroutine进行并行的累加计算,待2个计算过程都完成后打印计算结果:
package main
import (
"fmt"
)
func sum(values []int,resultChan chan int){
sum :=0
for _, v := range values{
sum + = v
}
resultChan <- sum //将计算结果发送到channel中
}
func main(){
values :=[]int{1,2,3,4,5,6,7,8,9,10}
resultChan := make(chan int,2)
go sum(values[:len(values)/2],resultChan)
go sum(values[len(values)/2:],resultChan)
sum1,sum2 :=<-resultChan , <- resultChan //接收结果
fmt.Println("Result:",sum1,sum2,sum1+sum2)
}