[Go语言进阶——工程进阶|青训营笔记]
这是我参加「第五届青训营」伴学笔记的创作活动的第二天
前言
记录go语言学习笔记,有不足的地方还请大佬指正。
由于本人基础较为薄弱,所以笔记尽可能详细。
一、了解Go高性能的本质
这里将从并发编程的视角去看待Go语言高性能的本质
在Go语言里,我们Goroutine来开启一个协程来开启并发编程。
下面简述一下和别的编程语言进行并发编程的区别:
- 线程与协程的开销区别:线程是用户态级别程序,是轻量级线程,所需栈是Mb级别。而协程是内核态级别程序,一个线程跑多个协程,所需栈是kb级别。
开启一个协程只需要用go关键字加一个函数即可。
二、线程通信
GoLang建议“通过通信实现共享内存”而不是“通过共享内存进行通信”,因为使用共享内存进行通信难免需要枷锁,这回降低程序性能。GoLang 通过“通道”(channel)进行 goroutine之间的通信。
创建 channel 使用make :
ch := make(chan int) // 无缓冲区双向
ch1 := make(chan int, 2) // 有缓冲区双向
chi := make(<-chan int) // 只读
cho := make(chan<- int) // 只写
使用<-将数据写入 channel 或从 channel 读取数据,使用range遍历 channel 中的数据
- 对于不带缓冲区的通道,接受方获取数据前发送方会阻塞
- 对于带缓冲区的通道,缓冲区满后发送方写入数据会导致写入线程阻塞
通道不再使用后,可通过close()函数来关闭,从而避免通道已空但接收方尝试读取导致阻塞的问题。
- 在通道未初始化时关闭、重复关闭、关闭后发送共和发送时关闭会导致 panic
线程同步
sync包提供了基础的线程同步锁,创建一个互斥锁的方式如下:
var lock sync.Mutex
复制代码
该互斥锁使用Lock()和Unlock()方法对编辑共享内存的代码块加锁,保证线程同步。
有时候我们需要在主线程执行到某个位置时开启多个子线程执行其他任务,且在这些子线程全部结束前阻塞主线程,这时我们就需要WaitGroup:
var wg sync.WaitGroup
复制代码
WaitGroup有三个方法:Add(delta int)用于计数器增加 delta ;Done()用于表示一个线程完成;Wait()用于阻塞主线程。