这是我参与「第五届青训营」伴学笔记创作活动的第 2 天
进程、线程和协程,并发和并行 | 青训营笔记
今天是工程实践,讲了我觉得是 Go 语言最重要的特性 goroutine。
想要明白这究竟是个什么,我想还是有必要了解下面这些东西的。
进程、线程、协程
说起来,现在一共有三个程,进程、线程、协程。
进程
进程还是比较好区分的,一般来说,双击打开一个应用,就是启动了一个进程,而这个在这个进程内部一般也只能创建线程,除非调用系统相关函数进行操作。而进程之间也是内存不共享的,基本上要做到进程间通信是没有那么方便的
线程
线程是包含在进程里的,它才是进程中的实际运作单位。我们平常写 C++ 之类的语言,main 函数一般就是属于一个主进程。而我们创建的 thread,就是主线程所创建的子线程。
线程的好处在于同一个进程的线程之间是可以共享内存的,因此可以比较方便地进行数据传输,至于由此引起的数据竞争的问题,那就是后话了。
如果主线程要结束了,那么子线程也是必定需要结束的。这就告诉我们在退出主线程之前想想子线程的事情有没有做完,没做完还是老老实实等吧。比起主线程死亡带着其他的子线程跟着暴毙,还是优雅点地退出比较好。
协程
goroutine 就属于协程。协程的话,我之前一度以为这是 Go 语言创造出来的一个概念,因为在 Go 之外基本没怎么听说过。后来才知道原来是我孤陋寡闻了,协程的概念在很早之前就有了,而且即使是这十几年来协程也不是由 Go 语言首先应用的。
不过我觉得就对协程的喜爱程度来说,可能无语言能出 Go 其右了,只需要一个 go,便能创建出一个协程。它对于协程喜爱至深,以至于程序启动的 main 函数,其实也是一个协程,甚至是主协程!
虽然协程经常被说是轻量级的线程,但我觉得“线程”这两个字总不免会让人觉得各个协程之间是并行的,然而实际上它们是在同一个线程里并发执行的。
并发和并行
下面说说并发和并行的区别
关于并发和并行的区别,我认为下面这张图还是能比较好地说明的:
图中,上方的是并发,下方的是并行。
可以把每行队列看做是一个单独的任务,咖啡机则是 CPU 核心(实际上并不完全准确,但也可以这么认为),一般也就是对应着一个线程。
并发就是多个任务同时要使用一个线程。但一个时间点只能有一个任务被线程执行,所以在别的任务暂时不需要执行的时候,就可以把资源抢过来执行自己的任务;而并行则是多个任务各自享有一个线程,它们的任务是同时执行的,不会和其他任务有执行的冲突。也正是因此,也就只有多核处理器才会真正有并行的能力,否则一般也都只是并发。
之前看到别人说过的一句话:“并发是一个时间段上有多个任务执行,并行则是一个时间点有多个任务执行。”我颇以为妙。
至于更深层次的内容,以及其他的内容,有大佬不仅写得比我好,也写得比我多,所以我就结合我的认识只写了这一点。因此如果这篇笔记能对你有帮助的话,我就很高兴了。