串行、并行、并发
让我们想象一个人慢跑。当他晨跑时,假设他的鞋带解开了。现在这个人停止了跑步,系好鞋带,然后又开始跑步。这是并发的一个典型示例。这个人能够处理跑步和系鞋带,也就是说,这个人能够同时处理很多事情。
并行指的是多个事情在 同一个时间点 上同时发生了。
并发指的是多个事情在 同一时间段 内同时发生了。
Go 是一种并发语言,而不是一种并行语言。
进程(Process)(并行运算,分布式)
定义:进程就是程序在操作系统中的一次执行过程,是系统进行资源调度和分配的基本单位。每个进程都有自己的一套独立的地址空间,这意味着进程间的内存是不共享的,每个进程都像是操作系统中的一个独立实体。比如,你打开一个浏览器,这就是一个进程;再打开一个文档编辑器,这是另一个进程。每个进程都有自己的空间,不会互相干扰。
资源:进程拥有独立的资源,包括内存、文件描述符、环境变量等。
调度:进程由操作系统进行调度,操作系统决定哪个进程在何时运行。
单道批处理系统内存中始终只保持一道作业,cpu 只能将内存中作业执行完毕,才能执行下一道作业,进程之间串行执行,A、B、C 三个进程按顺序执行
分时系统引申出了时间片的概念,进程按照调度算法分时间片在 CPU 上执行,A、B、C 三个进程按照时间片并发执行
线程(Thread)(并发执行)
在进程的基础上再细分出线程,线程比进程更轻量,线程之间的通信也更为便捷,任务的最小载体变成了线程。
定义:线程是进程中的一个实体,是被系统独立调度和分派的基本单位,是程序执行的一个最小单位。线程自身不拥有系统资源,只拥有一点在运行中必不可少的资源(如执行栈),但它可以与同属一个进程的其他线程共享进程所拥有的全部资源。
并行执行:在多核处理器上,同一个进程中的多个线程可以并行执行,即同时在不同的处理器上运行。
共享资源:同一进程内的线程共享进程的资源,包括内存、文件句柄等,但每个线程有自己的程序计数器、寄存器和堆栈。
CPU 内核负责调度,为系统提供并发处理能力。
协程是在用户空间实现的, CPU 并不知道有 “用户态线程” 的存在,CPU 只知道它运行的是一个 “内核态线程”。
这里我们可以把 内核线程依然叫“线程(thread)”,用户线程叫“协程(co-routine)”。
线程越多,进程利用(或者)抢占的cpu资源就越高。
进程和线程的创建、切换和销毁都会消耗大量 CPU 资源。
每个线程约需 4MB 内存,大量线程会导致内存消耗过高。应用层无法直接控制内核调度,只能通过减少线程创建和切换来优化性能。这促生了协程的概念:用户级别的轻量线程。
协程(Coroutine)(并发执行)
定义:协程是一种程序组件,它允许挂起和恢复执行。goroutine是由Go运行时管理的轻量级线程,与coroutine只能运行在一个线程上不同,goroutine可以运行在一个或多个线程上。
轻量级:goroutine比线程更加轻量级,因为它们的栈是动态的,并且可以在运行时调整大小,它们的堆栈大小只有几 kb,并且堆栈可以根据应用程序的需要进行扩展和收缩,而对于线程,则必须指定堆栈大小并固定堆栈大小。
并发执行:在Go语言中,goroutine可以在单个操作系统线程中并发执行,Go运行时会负责调度这些goroutine,让它们在线程之间高效地共享和切换。
共享资源:多个goroutine共享同一个线程的资源,但拥有自己的栈和寄存器。它们通过channel进行通信,这是一种同步机制,可以用来传递数据和同步goroutine。
Go 协程和线程的区别
Go 语言引入了 goroutine
(协程),它是一个比线程更轻量级的并发执行单元。
更小的内存占用:
每个线程的栈内存通常是固定的(通常为 1MB 或更多)。
goroutine
的栈内存默认仅占用约 2KB,可以根据需要自动增长和收缩。
调度机制不同:
线程由操作系统调度,切换线程的开销较大,因为需要在用户态和内核态之间切换。
goroutine
是由 Go 运行时(runtime)调度的,属于用户态调度,切换开销更小。
什么是runtime?
Go语言程序执行的环境,它提供了一些底层服务,
并发支持(goroutine)和协程调度
,垃圾回收
,内存管理
,反射
,网络和文件I/O
。数量可达数十万:
创建一个线程的系统开销很大,不适合大规模并发。
goroutine
非常轻量,因此可以轻松创建成千上万个goroutine
,并发处理大量任务。
goroutine 的基本使用
goroutine
是 Go 中的轻量级线程,启动一个 goroutine
只需要使用 go
关键字,非常高效。每个 goroutine
都是独立的,多个 goroutine
可以并发执行。
1 | package main |
1 | package main |
1 | 这是在主 goroutine 中 |
参考链接
操作系统篇一:进程与线程、并发并行与串行、同步与异步、阻塞与非阻塞当你被问到这些问题:你觉得的并发、并行、串行有什么区别 - 掘金
第三篇、Golang编程设计与通用之路 - 3、对于操作系统而言进程、线程以及Goroutine协程的区别 - 《Golang 修养之路》 - 书栈网 · BookStack
翻译来自 Goroutines