阅读 252

Go中的协程 | Go主题月

前言

这是一篇为了写Go中并发而写的一篇前置性质的文章,因为内容会比较多,所以就单独开一篇博客来写了。(其实是为了大茶缸

我们知道在Go中的使用的是协程,这跟我们之前接触到的,不管是JavaScript中的单线程(父子进程),还是Java中的多线程的概念都不太一样,这里我就来聊一下,这三者之间的一些观点。

进程和线程

其实我们每天在操作计算机的过程,这里就有进程的关系,例如,我现在打开了谷歌浏览器,然后进入掘金的网站在写这篇文章的过程,其实在计算机的内部,我就是启动了一个谷歌浏览器的进程,而我在这里疯狂打字的过程,计算机拼音把我打出来的一个个字母识别成汉子的过程,这个就是通过线程来完成的。

aHR0cHM6Ly81YjA5ODhlNTk1MjI1LmNkbi5zb2h1Y3MuY29tL3FfNzAsY196b29tLHdfNjQwL2ltYWdlcy8yMDE4MDYyMi82MjYwYTdhMGUwNWM0YjE5YTliNzQ2NWM4ZTU2MDUzZS53ZWJw.webp

我们知道一个CPU只能在同一时刻只能执行一条进程任务,也就是说,当一个进程开始被这个CPU执行的时候。其他进程任务是被挂起的,正常来说是要CPU执行完这个进程之后,才会去执行其他的进程的,但是因为计算机系统的内部,存在一个调度器,用来调度各个进程在CPU下面的执行。

例如一共有AB两个进程,A执行了0.3秒,然后调度器会让B执行,而A的执行过程会被保存,之后等B执行了一段时间,或者执行完毕之后,再切回来继续执行A进程。

需要注意的是:

进程是资源分配的基本单位

线程是CPU调度分配的基本单位

也就是进程是作用于整个计算机系统的,但是线程只是作用于执行这个进程的那个CPU。因此一个CPU只能执行一个进程,但是一个进程里面却可以有很多条线程,同时进程之间是相互隔离的,但是线程之间确实相通的。

这样说起来可能会一点抽象,用一个比较实际的例子—— 英雄联盟。

在撸啊撸里面,一个游戏的房间,好比是一个CPU,而这个房间里面可以有1~10个玩家参与游戏,这十个玩家只能在这场对局里面相互之间对垒(线程间的消息互通),而不会与其他房间的玩家发生互动(进程间的相互隔离)。

由于这些特性,也就衍生出了多线程和多进程的模型概念,但因为进程和线程都不是本篇所要讲的重点,所以这里我就不说了。

Go中的“协程”

协程其实跟线程非常的类似,但是却有些许的不同,这里先说一下协程的一些比较明显的特点:

  1. 多线程是通过交替切换线程来执行,协程也是,不同点是,线程的切换是操作系统来执行的,而协程的切换则是通过用户自己来进行调度的,例如在Go中的任务调度器等,这里就减少了上下文的切换所带来的开销问题。

  2. 创建协程所需要的内存空间更小,一般情况下,一条线程所需要的内存大小为1M左右,但是一条协程的大小却是差不多2K,所以相对应的,创建一条线程的空间大小,可以提供创建更多的协程。

  3. 由于协程在执行的时候,其实只有一个线程在执行,这样就避免了多线程在执行的时候的读写问题,也就是锁机制,在线程里面只需要通过判断状态来进行切换就可以了。(例如Go中的Chan)

  4. 适用于高并发的场景,而不适用于需要高密度的计算的场景。

在Go中想要创建一条协程也非常的简单

	go func() {
            ...执行的内容
	}()	
复制代码

只需要通过简单的一个go就可以了,非常方便。

这里放一张网上找来的协程和线程之间的差别的图。

image.png

最后

因为这只是一篇前置类型的文章,所以我不会过多的去探讨Go语言中的例如并发和通道之间的运用(其实就是懒),那么祝大家周末愉快~~

文章分类
后端
文章标签