这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
Go语言进阶
并发编程
并发 vs 并行
- 多线程程序在一个核的cpu上运行---并发
- 多线程程序在多个核的cpu上运行---并行
go可以由标准库支持天然支撑高并发,可以充分发挥多核优势,高效运行程序。
Goroutine
内核态中分为多个线程,创建和删除一个线程的开销都比较大。而go语言中的协程则属于用户态的部分,可以理解为轻量级线程,创建和删除的开销都比较小。
- 协程:用户态,轻量级线程,栈KB级别
- 线程:内核态,线程跑多个协程,栈MB级别
如,多goroutine快速打印。
由于除了main goroutine以外开了5个goroutine同时进行对i进行打印,得出的结果顺序自然是随机的。其中的一种结果为:
CSP(Communicating Sequential Processes)
- 通过通信共享内存
- 通过共享内存实现通信
通过通信共享内存需要使用channel
Channel
Channel是一种引用类型,使用make关键字来创建,根据是否有缓冲通道可以分为
- 无缓冲通道
make(chan int)也称为同步通道 - 有缓冲通道
make(chan int,2)表示有两个缓冲通道的channel,也是一种经典的生产消费模型
如通过两个子协程使用channel发送相关数据,最后由主协程输出最后的结果。
结果如下
可以发现使用此例中使用channel来传递数据是可以保证顺序的,也就是说channel的这种使用方式是并发安全的。带缓冲的channel可以解决生产消费中的速度问题
并发安全Lock
此例中分别使用五个协程来计算2000次的x += 1,分别使用有锁的函数和无锁的函数来实现循环累加。具体的代码如图所示:
预期的结果应该是五个协程各加2000得到最终结果10000.但实际的两个函数的结果不同。
无锁的函数的运行结果是未知的,也就是并发不安全的问题,而有锁的函数运行结果符合预期,是并发安全的。
未完待续......