字节一面:go的协程相比线程,轻量在哪?
1. 用户态和内核态
Linux整个体系分为用户态和内核态(或者叫用户空间和内核空间), 那内核态究竟是什么呢?
本质上我们所说的内核态, 它是一种特殊的软件程序,特殊在哪?
统筹计算机的硬件资源,例如协调CPU资源、分配内存资源、并且提供稳定的环境供应用程序运行。
2. 为什么线程切换会导致用户态和内核态的切换?
- 线程是cpu调度的基本单位,进程是资源占有的基本单位。
- 因为线程中的代码是在用户态运行,而线程的调度是在内核态,所以线程切换会触发用户态和内核态的切换。
- 线程上下文切换的代价是高昂的:上下文切换的延迟取决于不同的因素,大概是50到100 ns左右,考虑到硬件平均在每个核心上每ns执行12条指令,那么一次上下文切换可能会花费600到1200条指令的延迟时间。
3. 导致线程上下文切换的时机
<1>. 自发性上下文切换 | 自发性上下文切换指线程由于自身因素导致的切出 |
---|---|
Thread.sleep() | 线程主动休眠 |
object.wait() | 线程等待锁 |
Thread.yield() | 当前线程主动让出CPU,如果有其他就绪线程就执行其他线程,如果没有则继续当前线程 |
oThread.join() | 阻塞发起调用的线程,直到oThread执行完毕 |
<2>. 非自发性上下文切换:线程由于线程调度器的原因被迫切出 |
---|
线程的时间片用完 |
高优先级线程抢占 |
虚拟机的垃圾回收动作 |
4. 线程切换的开销
<1>. 直接开销 |
---|
保存/恢复上下文所需的开销 |
线程调度器调度线程的开销 |
<2>. 间接开销 |
---|
重新加载高速缓存 |
上下文切换可能导致 一级缓存被冲刷,写入下一级缓存或内存 |
4. go的协程轻量级体现在哪?
如上面所述,线程切换会导致 用户态和内核态的切换,其中内核态耗时较长,且不受用户代码控制。
go将goroutine的调度维持在用户态, 这是由GPM中的P Process来完成的,做用户态任务的调度器,功能类比于常规的操作系统线程调度器,所以又被称为逻辑处理器。
P 是G、M之间的桥梁,调度器对于goroutine的调度,很明显也会有切换,这个切换是很轻量的: 只涉及PC SP DX三个寄存器的值的修改;而对比线程的上下文切换则需要陷入内核模式、以及16个寄存器的刷新。
5. GO GMP 调度方式
- 由逻辑处理器P调度协程G进系统线程M (若本地队列没有G,从其他队列/全局队列偷取G),
- 线程M执行G, 遇到[系统调用], G和M分离,拿新的M去接管原逻辑处理器P
请仔细阅读上图,出处不可考证,感谢原图作者。
这里特意指出网络IO操作不会走上图的模型,否则要分配的系统线程M依然很多,程序很快就爆满了。这时G会和逻辑处理器P分离,并移动到netpoller,一旦网络轮询器通知网络读/写就绪,对应G就会重新分配到逻辑器处理器上来完成操作, 在此期间原系统线程M可以去做别的G。
ref
- https://blog.csdn.net/No_Game_No_Life_/article/details/106100813
- https://zhuanlan.zhihu.com/p/261807834
- https://chende.ren/2020/12/27221039-008-gmp-model.html
- https://studygolang.com/articles/12328
- https://www.jianshu.com/p/cc3c0fefee43
字节一面:go的协程相比线程,轻量在哪?的更多相关文章
- unity3D中协程和线程混合
这是我google unity3D一个问题偶然发现的在stackflow上非常有趣的帖子: 大意是 要在unity3D上从server下载一个zip,并解压到持久化地址.并将其载入到内存中.以下展示了 ...
- day37协程与线程套接字通讯
协程与线程套接字通讯基于多线程实现套接字服务端支持并发,服务端 from socket import * from threading import Thread def comunicate(con ...
- [Sw] 使用 Swoole Server task/协程 处理大数据量异步任务时注意
关于 Buffered Query 和 Unbuffered Query:http://www.php.net/manual/zh/mysqlinfo.concepts.buffering.php 对 ...
- paip.提升性能---协程“微线程”的使用.
paip.提升性能---协程的使用. 近乎无限并发的"微线程" 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:h ...
- Unity 协程与线程
协程是不同步的 协程 不是 线程,协同程序是 不同步 的 一个线程在程序中和其他线程是异步运行的,在多处理器机器中一个线程可以同时与所有其他线程的实时运行其代码,这使得线程编程能够解决很复杂的事情,因 ...
- I/O多路复用、协程、线程、进程
select注册fd,阻塞,当有fd状态改变时返回,确认对应的fd,做下一步处理.简单来说就是先注册,注册完后休眠并设置一个定时器醒来查看,有事件就通知来取,进行后续动作,没事件就继续睡,再设闹钟.用 ...
- lua协程----ngx-lua线程学习笔记
--[[ - @desc lua数据输出 - @param string 字符串 - return string --]] function dump(v) if not __dump then fu ...
- (day31) Event+协程+进程/线程池
目录 昨日回顾 GIL全局解释器锁 计算密集型和IO密集型 死锁现象 递归锁 信号量 线程队列 FOFI队列 LIFO队列 优先级队列 今日内容 Event事件 线程池与进程池 异步提交和回调函数 协 ...
- Lua 协程和线程区别
协程就是协程,不是线程. CPU执行单位是线程,不是什么协程. 协程,是同步执行,不是并行,只是切了一个上下文了,为你保存原来的上下文而已. 切到第二个协程时,原来的协程处于挂起状态. 这个特指lua ...
随机推荐
- 使用estimatedRowHeight的优缺点
使用estimatedRowHeight的优缺点 1.优点 1> 可以降低tableView:heightForRowAtIndexPath:方法的调用频率 2> 将[计算cell高度的操 ...
- js演示面向对象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- JAVA多线程学习十一-线程锁技术
前面我们讲到了synchronized:那么这节就来将lock的功效. 一.locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---Abst ...
- docker构建镜像 (3)
使用Dockerfile构建镜像 Dockerfile使用DSL(Domain Specific Language)来构建一个Docker镜像,只要编辑好了Dockerfile文件,就可以使用dock ...
- 【HDU6687】Rikka with Stable Marriage(Trie树 贪心)
题目链接 大意 给定\(A,B\)两个数组,让他们进行匹配. 我们称\(A_i\)与\(B_j\)的匹配是稳定的,当且仅当目前所剩元素不存在\(A_x\)或\(B_y\)使得 \(A_i\oplus ...
- Scala函数高级篇
一.匿名函数 没有名字的函数就是匿名函数,格式:(x:Int)=>{函数体} x:表示输入参数类型:Int:表示输入参数类型:函数体:表示具体代码逻辑 传递匿名函数至简原则: 参数的类型可以省略 ...
- 配置samba共享,实现/www目录共享
一.samba服务器 1.安装samba包 # yum -y install samba 2.创建用户组 # groupadd -r admins # useradd -s /sbin/nologin ...
- 从服务间的一次调用分析整个springcloud的调用过程(二)
先看示例代码 @RestController @RequestMapping("/students") public class StudentController { @Auto ...
- 06 前端之Bootstrap框架
目录 前端之Bootstrap框架 一.简介 二.引入方式 本地引入(最完整的) CDN引入 三.布局容器 四.栅格系统 五.列偏移 六.表格与表单 6.1表格 6.2表单form 七.按钮 预定义样 ...
- Solution -「ZJOI 2019」「洛谷 P5326」开关
\(\mathcal{Description}\) Link. 有 \(n\) 个开关,初始时所有开关的状态为 \(0\).给定开关的目标状态 \(s_1,s_2,\cdots,s_n\).每 ...