并发的概念及其重要性
这段是简单科普,大佬可以跳过
在聊并发之前,聊聊共享变量、线程、协程
- 如何在不同线程/协程 共享 变量/内存?
这里留给各位看官去自行查资料,即使我列出来也不如自己动手去查记忆深刻!
不想查也可以等我下一篇文章,更加详细解读线程、进程。
- 线程和协程概念?
线程:线程是操作系统能够进行运算调度的最小单位。一个进程可以包含多个线程,是进程中的实际运作单位。
协程:又称微线程。协程是一种用户态的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。
- 为什么会诞生协程?
虽然多线程在前互联网世代已经足够使用,但是线程的局限性也比较明显
- 线程数量有限,一般不会很多
- 线程占据的资源通常比我们需要的多得多,造成浪费
每个系统级线程开辟都会占用空间,这个空间可能是MB级别,但是我们如果使用的线程只需要传递KB级别数据,那么线程看起来就会比较浪费,但是又不可避免。而且线程之间的切换也会占用一些额外开销。
为了解决上面的矛盾问题,协程诞生了:更小的资源开支,动态调配资源,比线程更轻量。
协程的一些优点:
- 因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
- 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
在golang中,goroutine的创建消耗非常小,大约是KB级别。因此可以创建更多的协程,尤其是数量越多相对线程优势更加明显,而且goroutine可以动态伸缩,栈溢出风险也比线程更低。
golang的并发,goroutine的使用
var name = "yiyiyinhe"
func changeName() {
name = "change"
}
func sayHi() {
fmt.println("hi, ", name)
go changeName() // 协程
}
简单的协程就创建了,那么打印出来的结果可能是hi, yiyiyinhe
也可能是hi, change
。
如果想对某一代码块执行协程而不是某个方法,则使用下面方式
var name = "yiyiyinhe"
func sayHi() {
fmt.println("hi, ", name)
go func() { // 匿名函数执行协程
name = "change"
}
}
channel
golang对共享变量的口号
那么在协程中也需要进行通信,而golang使用的goroutine之间通信和同步的主要方法是channel。
什么是channel呢?
简单来理解就是,channel是用于在goroutine中进行通信的管道,而且管道是有特定类型的。
创建的channel分为有缓存和无缓存两种,区别就是创建的时候是否分配大小
无缓存channel
var ch1 = make(chan int)
,未分配大小var ch2 = make(chan int, 0)
,分配大小为0也等同给于未分配大小
有缓存channel
var :ch3 = make(int, 3)
,分配大小为3的有缓存channel
在无缓存channel中,channel的发送操作总是在接收之前发生;简单理解就是,无缓存channel是一个管道必须从头flag<-true
发送到尾部<-flag
,而且尾部发生的时间一定是在头部发送之后。
为什么chennel可以这样呢?
因为channel有阻塞作用,必须接收了才能继续下去。
还是上面的例子,使用channel来演示一下
var name = "yiyi"
var flag = make(chan bool) // 创建了bool类型的channel
func changeName() {
name = "change"
flag <- true // 发送
}
func sayHi() {
go changeName() // 协程
<-flag // 接收
fmt.println("hi, ", name)
}
那么这个时候打印出来的就是一个固定的顺序,由于<-flag
接收总是在发送
之后执行,因此当flag <- true
执行完之前name = "change"
已经执行,打印结果一定是:hi, change
上面代码等同于下图所示
看完你可以收获什么?
- 简单了解并发,了解多线程简单的发展来历
- 简单了解线程,协程
- 为什么协程会诞生?
- goroutine的两种使用方式
- channel是什么?channel的两种分类;
- channel在goroutine中有什么作用?
写在最后
由于我刚开始写技术文章,很多东西不知道怎么写才能让大家都看懂,就像写线程协程的时候不知道要不要解释共享变量或者共享内存是什么,也不知道大家能不能知道多线程模式下线程之间通信有哪些方式,感觉都想写但是又觉得大家看文章标题应该是了解一些东西的,如果都写篇幅太长,不写又看不懂;就觉得比较矛盾吧,也希望大家能够给我提一些意见建议!
作者还在慢慢努力,尽量把文章写的通俗易懂,排版准确,抓住重点,把最好的内容展现给大家。