文章目录
- 一、进程和线程
- 进程和线程的痛点
- 为什么 Java 坚持多线程不选择协程?
- 二、什么是协程
- CSP并发模型
- golang 线程模型和GMP
- 一直创建协程会出什么问题
- 三、参考
一、进程和线程
进程就是应用程序的启动实例,进程拥有代码和打开的文件资源、数据资源、独立的内存空间。
线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。
线程拥有自己的栈空间。
对操作系统来说,线程是最小的执行单元,进程是最小的资源管理单元。
进程和线程的痛点
抢占式调度:操作系统会根据每个线程的优先级进行调度,决定他们的执行顺序。
多线程的优点:将主要进行io操作的线程(比如读取硬盘数据)的优先级调低,不会被io操作浪费大量的cpu时间
多线程的缺点:线程切换需要保存上下文,需要时间。
Java中线程具有五种状态:
这五种状态的转化关系如下:
但是,线程不同状态之间的转化是谁来实现的呢?是JVM吗?
并不是。JVM需要通过操作系统内核中的TCB(Thread Control Block)模块来改变线程的状态,这一过程需要耗费一定的CPU资源。
为什么 Java 坚持多线程不选择协程?
参考URL: https://www.zhihu.com/question/332042250/answer/734115120
二、什么是协程
线程的切换由操作系统负责调度,协程由用户自己进行调度,因此减少了上下文切换。
线程的默认Stack大小是1M,而协程更轻量,接近1K。因此可以在相同的内存中开启更多的协程。
由于在同一个线程上,因此可以避免竞争关系而使用锁。
Goroutine 是一个由 Go 运行时管理的轻量级线程,一般称其为 “协程”。操作系统本身是无法明确感知到 Goroutine 的存在的,Goroutine 的操作和切换归属于 “用户态” 中。Goroutine 由特定的调度模式来控制,以 “多路复用” 的形式运行在操作系统为 Go 程序分配的几个系统线程上。
据测试,一次协程的切换,耗时大概在100ns,相对于线程的微秒级耗时切换,性能表现非常优秀,但是仍有一些开销。
CSP并发模型
CSP模型是上个世纪七十年代提出的,用于描述两个独立的并发实体通过共享的通讯 channel(管道)进行通信的并发模型。 CSP中channel是第一类对象,它不关注发送消息的实体,而关注与发送消息时使用的channel。
Golang 就是借用CSP模型的一些概念为之实现并发进行理论支持,其实从实际上出发,go语言并没有,完全实现了CSP模型的所有理论,仅仅是借用了 process和channel这两个概念。process是在go语言上的表现就是 goroutine 是实际并发执行的实体,每个实体之间是通过channel通讯来实现数据共享。
golang 线程模型和GMP
多内核线程+多协程,以及Golang的GMP模型
参考URL: https://juejin.cn/post/6906420781182353422
go线程模型包含三个概念:内核线程(M),goroutine(G),G的上下文环境(P);Go语言运行时,通过核心元素G,M,P 和 自己的调度器,实现了自己的并发线程模型。
GMP模型
GMP模型是goalng特有的。
- G是goroutine,基于协程建立的用户态线程。实际上我们每次调用 go func 就是生成了一个G。
- M是machine,它直接关联一个os内核线程,用于执行G。
- P是processor,P里面一般会存当前goroutine运行的上下文环境(函数指针,堆栈地址及地址边界),P会对自己管理的goroutine队列做一些调度。一般P的数量就是处理器的核数,可以通过GOMAXPROCS进行修改。
一直创建协程会出什么问题
func main() {
maxCount := math.MaxInt64
for i := 0; i < maxCount; i++ {
go func(i int) {
// 做一些各种各样的业务逻辑处理
fmt.Printf("go func num: %d\n", i)
time.Sleep(time.Second)
}(i)
}
}
当程序运行起来后,可以看到CPU和内存开销,持续上涨~
默认每个 goroutine 占用 8KB 内存,那么一台8GB内存的机器大约能创建8GB/8KB = 1000000 个 goroutine,系统还需要保留一部分保证其他日常任务运行,因此当协程数创建到内存使用上限后,就会panic。
结论: 协程并不是可以无限创建,它收2个因素影响,文件句柄数量达到限制(panic: too many concurrent operations on a single file or socket)和内存(Out of Memory)。
三、参考
关于GO协程数控制的二三事
参考URL: https://zhuanlan.zhihu.com/p/568151296