GO语言快的原因| 青训营笔记

123 阅读2分钟

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

课堂笔记

本堂课重点内容

GO语言快的原因

GO可以发挥多核优势高效运行

详细知识点介绍

  • 并发

    • 多线程程序在一个核的CPU上运行
  • 并行

    • 多线程程序在多个核的CPU上运行

Gorotine

适合高并发是因为GO语言创建多个协程

  • 协程

    • 用户态
    • 轻量级线程
    • 栈MB级别
  • 线程

    • 内核态
    • 线程跑多个协程
    • 栈KB级别

只需要在调用函数的时候在函数前加上一个go的关键词即可

CSP(Communicating Sequential Processes)

通过通信来实现共享内存,而不是通过内存来实现共享通信

Channel(引用类型)<通信来实现共享内存>

make(chan 元素类型,[缓冲大小])

  • 无缓冲通道 make(chan int)

    • 接受和发送的Gorotine和发送的Gorotine同步化<同步通道>
  • 有缓冲通道 make(chan int ,2)

    • 接受和发送的Gorotine和发送的Gorotine异步化<异步通道>
  • 使用缓冲通道保证顺序性->保证并发安全

    • 消费者的逻辑复杂->消费速度慢
    • 生产者的逻辑简单->生产速度快

并发安全Lock<内存实现通信>

多种Gorotine同时操作一块内存资源->数据并发

  • 通过对权限的控制来保证并发安全

WaitGroup

无法精确知道协程进行的时间

  • 通过设置一个精确的sleep的时间——WaitGroup包
函数功能
Add(data int)计数器+data
Done()计数器-1
Wait()阻塞直到计数器为0
  • 执行所有子协程之前使用Add函数记录数目
  • 每执行完一个子协程就使用Done完成任务
  • 执行完子协程的函数在Wait处等待其他子协程执行结束

实践练习例子

举例——快速打印Hello goroutine

 func hello(i int) {
     println("hello goroutine : " + fmt.Sprint(i))
 }
 func HelloGORoutine() {
     for i := 0; i < 5; i++ {
         go func(j int) {
             hello(j)
         }(i)
     }
     time.Sleep(time.Second)
 }

举例——A子协程发送0-9,B子协程计算输入数字的平方,主协程输出最后的平方数

使用缓冲通道保证顺序性->保证并发安全

此时A子协程就是生产者->快速生产

B子协程就是消费者->慢速消费

 package main
 ​
 func main() {
     src := make(chan int)
     dest := make(chan int, 3)
     //A
     go func() {
         defer close(src)
         for i := 0; i < 10; i++ {
             src <- i
         }
     }()
     //B
     go func() {
         defer close(dest)
         for i := range src {
             dest <- i * i
         }
     }()
     //M
     for i := range dest {
         println(i)
     }
 }
 ​

举例——对变量执行2000+1次操作,5个协程并发进行

通过结果可以发现没有Lock的打印结果并非10000,并且无规律

 package main
 ​
 import (
     "sync"
     "time"
 )
 ​
 var (
     x    int64
     lock sync.Mutex
 )
 ​
 func addWithLock() {
     for i := 0; i < 2000; i++ {
         lock.Lock()
         x += 1
         lock.Unlock()
     }
 }
 func addWithoutLock() {
     for i := 0; i < 2000; i++ {
         x += 1
     }
 }
 func main() {
     x = 0
     for i := 0; i < 5; i++ {
         go addWithoutLock()
     }
     time.Sleep(time.Second)
     println("WithoutLock : ", x)
     x = 0
     for i := 0; i < 5; i++ {
         go addWithLock()
     }
     time.Sleep(time.Second)
     println("withLock : ", x)
 }
 ​

课后个人总结

  • go语言的快是建立在协程的基础上
  • 需要好好掌握协程相关的函数来充分发挥go语言快的性能