Go语言之并发编程篇 |青训营笔记

95 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记

以下我对并发编程六个方面的总结笔记,并且用两个简单的代码举例说明知识的理解

并发编程

  1. 并发与并行的区别:并发是多线程程序在一个核的CPU上运行,并行是多线程程序在多个核的CPU上运行
  2. 协程:轻量的线程 (快速)
  3. CSP:(Communicating Sequential Processes):通过通信共享内存
  4. 两种channel:
    • 无缓冲通道:make(chan int)

    • 有缓冲通道:make(chan int,2)

    我们用下面代码更好地去理解以上概念
1. func CalSquare(){
2.     src := make(chan int)
3.     dest := make(chan int, 3)
4.     go func(){
5.         defer close(src)
6.             for i :=0; i < 10; i++ {
7.                 src <- i
8.             }
9.     }()
10.     go func(){
11.         defer close(dest)
12.         for i :=range src{
13.             dest <- i+1
14.         }
15.     }()
16.     for i := range dest{
17.         println(i)
18.     }
19. }
          

第2行和第3行的代码分别构建了一个无缓冲通道src和有缓冲通道dest.代码第4行至第9行是一个子协程A,其中将i的值发送到src通道里.代码第10行至第15行是子协程B,在这个子协程中遍历了src通道,实现了A与B协程之间的通信.在B协程中计算数字的平方,放到了dest通道里。最后通过代码16至18行,主协程遍历有缓冲通道依次输出结果。

这里面包括了无缓冲通道src,有缓冲通道dest的建立,以及协程的构建与使用(目的:加快执行速度)和通过通信共享内存的代码举例,很好地说明了上述知识点

  1. 并发安全:如果通过共享内存实现通信(i.e. 多个routine 共同操作一个资源内存)会有一定概率出bug,解决方案获取临界区资源lock

  2. 计数器:WaitGroup

    • add(delta int) #加delta个并发任务
    • Done() #计数器-1
    • wait() #阻塞直至计数器为0
1. func ManyGoWait(){
2.     var wg sync.WaitGroup
3.     wg.Add(5)
4.     for i := 0; i<5; i++{
5.         go func(j int){
6.             defer wg.Done()
7.             hello(j)
8.         }(i)
9.     }
10.     wg.Wait()
11. }

在代码的第3行利用了add构建五个子协程。在代码第6行利用Done对计数器进行-1操作,经过五次遍历,计数器成为了0.最后,代码第10行通过Wait来阻塞。