Go的并发编程| 青训营笔记

36 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2天

1.前言

Go语言的并发通过goroutine实现。goroutine类似于线程,是一种协程,我们可以根据需要创建成千上万个goroutine并发工作。goroutine是由Go语言的运行时(runtime)调度完成,而线程是由操作系统调度完成。

Go语言还提供channel在多个goroutine间进行通信。goroutine和channel是 Go 语言秉承的 CSP(Communicating Sequential Process)通过通讯共享内存的并发模式的重要实现基础。goroutine是非常轻量级的线程。其实goroutine和channel之间的关系,相当于进程与队列之间的关系。

2.goroutine

将一个任务包装进函数,便可轻松使用goroutine执行此函数实现并发,方便快捷。

2.1.启动线程实例

func hello() {
   println("hello world")
}

func main() {
   go hello()
   time.Sleep(time.Second)
}

3.sync.WaitGroup

sleep去等子线程结束有弊端,主进程再退出,存在可能等多了,可能等少了这种情况,因此需要有一种优雅的方式去结束主进程即sync.WaitGroup

func hello(i int) {
   println("hello world : " + fmt.Sprint(i))
}

func ManyGo() {
   var wg sync.WaitGroup
   for i := 0; i < 5; i++ {
      wg.Add(1)
      go func(j int) {
         defer wg.Done()
         hello(j)
      }(i)
   }
   wg.Wait()
}

上例代码中,wg.Add(delta int):计数器加delta,wg.Done():计数器减一,wg.Wait():阻塞直到计数器为0。

4.channel

Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信 goroutine是Go程序并发的执行体,而channel是协程之间的连接,goroutine通过channel通信,类似于进程通信通过队列先进先出的规则,保障了并发的安全性。 channel是一种类型,一种引用类型。声明的通道后需要使用make函数初始化之后才能使用。通道有发送(send):<-接收(receive):->关闭(close):close(channel)三种操作。

func CalSquare() {
   src := make(chan int)
   dest := make(chan int, 3)
   go func() {
      defer close(src)
      for i := 0; i < 10; i++ {
         src <- i
      }
   }()
   go func() {
      defer close(dest)
      for i := range src {
         dest <- i * i
      }
   }()
   for i := range dest {
      println(i)
   }
}

以上src是无缓冲通道,dest为有缓冲通道,二者区别如下:

1.使用无缓冲通道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也被称为同步通道。

2.有缓冲通道的容量表示通道中能存放元素的数量。就像学校的快递柜只有那么个多格子,格子满了就装不下了,就阻塞了,等到别人取走一个快递员才能往里面放一个。

Go语言相较java等语言的并发编程,有goroutine这个轻量级“线程”,使得高并发变得易处理,更高效。