GO语言并发编程
1. Goroutine
协程:用户态,轻量级线程,栈kB级别
线程:内核态,一个线程跑多个协程,栈MB级别
在go里面,每一个并发执行的活动称为goroutine。
goroutine可以认为是轻量级的线程,与创建线程相比,创建成本和开销都很小,每个goroutine的堆栈只有几kb,并且堆栈可根据程序的需要增长和缩小(线程的堆栈需指明和固定),所以go程序从语言层面支持了高并发。
程序执行的背后:当一个程序启动的时候,只有一个goroutine来调用main函数,称它为主goroutine,新的goroutine通过go语句进行创建。
使用姿势:在函数或者方法前面加上关键字go,即创建一个并发运行的新goroutine。
2. CSP(Communicating Sequential Processes)
不同于传统的多线程通过共享内存来通信,CSP讲究的是“以通信的方式来共享内存”。
普通的线程并发模型,就是像Java、C++、或者Python,他们线程间通信都是通过共享内存的方式来进行的。非常典型的方式就是,在访问共享数据(例如数组、Map、或者某个结构体或对象)的时候,通过锁来访问,因此,在很多时候,衍生出一种方便操作的数据结构,叫做“线程安全的数据结构”。
Go的CSP并发模型,是通过goroutine和channel来实现的。
goroutine 是Go语言中并发的执行单位。可以理解为用户空间的线程。 channel是Go语言中不同goroutine之间的通信机制,即各个goroutine之间通信的”管道“,有点类似于Linux中的管道。
3.Channel
如图中所示,定义了两个管道src和dest。A作为生产者存入src,B作为生产者和消费者,从src中获取并存入dest,M消费dest。
4.并发安全Lock
利用Golang中的Mutex信号量,可实现加锁和解锁,实现对变量的互斥访问。
5.WaitGroup
主线程为了等待goroutine都运行完毕,不得不在程序的末尾使用time.Sleep() 来睡眠一段时间,等待其他线程充分运行。对于简单的代码,100个for循环可以在1秒之内运行完毕,time.Sleep() 也可以达到想要的效果。但是对于实际生活的大多数场景来说,1秒是不够的,并且大部分时候我们都无法预知for循环内代码运行时间的长短。这时候就不能使用time.Sleep() 来完成等待操作了。
上图中,WiatGroup解决方案,这里首先把wg 计数设置为5, 每个for循环运行完毕都把计数器减一,主函数中使用Wait() 一直阻塞,直到wg为零——也就是所有的5个for循环都运行完毕。相对于使用sleep和管道来说,WaitGroup 轻巧了许多。
以上是Golang语言并发编程的一瞥,其中部分截图来自于字节青训营内部课PPT分享,部分文字来自CSDN社区,感谢以上内容创作者的分享,若有侵权行为请联系我,会第一时间进行删除,感谢!