问一个协程方面的问题

2021-12-13 15:04:45 +08:00
 kingofzihua

协程究竟解决了什么问题,都在吹协程,像是 go 、kotlin 都有协程,java 本身没有协程,

还有相比于线程,协程的优势是什么,为啥 java 没有协程,性能框架和 go 框架不相上下,协程这么牛逼为啥 rust 没有内置协程(听说都已经写好了,但是不符合理念,没合并)

操作系统调度的时候是以线程为单位调度的,又不知道协程的存在,即使你用协程了,操作系统还是只知道你是线程啊。

各种博客,都只说了比线程更轻量,占用内存小,切换成本小,但是线程切换是操作系统决定的,系统切换线程,你协程也没用啊。

各位大佬,救救孩子吧。

13639 次点击
所在节点    Linux
155 条回复
virus94
2021-12-13 15:07:41 +08:00
同疑惑,帮顶
joApioVVx4M4X6Rf
2021-12-13 15:09:29 +08:00
等待大神解答
cityboy
2021-12-13 15:10:15 +08:00
相当于自己在一个线程了完成了多个协程的切换,不需要系统进行一些状态的切换,线程切换需要耗费一点的性能。看你项目的使用场景,如果本身项目是多线程的项目,通过协程确实可以提高一些效率。如果本身项目就不是多线程的,就没必要切换到协程。
kingofzihua
2021-12-13 15:11:49 +08:00
@cityboy 我一个线程内为啥要进行多个协程切换?
nebkad
2021-12-13 15:12:35 +08:00
可以从跨线程调用、回调函数的应用场景出发思考这个问题。
甚至再简单一点,生成一个无限的 Fibonacci ,如何写代码才最贴近它的数学定义。
airplayxcom
2021-12-13 15:13:02 +08:00
洗牌 码牌 胡了 结算
2kCS5c0b0ITXE5k2
2021-12-13 15:14:31 +08:00
@kingofzihua 因为任务.. 有些任务不需要那么重的线程 那我就可以起一个协程来用.
anonydmer
2021-12-13 15:17:18 +08:00
楼主需要了解的是线程的切换需要哪些成本。
cclin
2021-12-13 15:18:33 +08:00
我的理解是把任务调度从系统交还给程序员自己。
线程的调度是由操作系统来控制的,协程则是程序主动让出资源。所以协程性能会好点。
不知道理解的对不对,有没有大佬解惑。
shyrock
2021-12-13 15:18:37 +08:00
我理解协程是非抢占式的多任务调度,并且由应用开发者自己维护其调度逻辑。
这样就可以由应用开发者根据业务具体需要有针对性地定制调度逻辑,而不是只能适应系统的调度逻辑。
cityboy
2021-12-13 15:19:27 +08:00
@cityboy 这个问题要重源头开始想,例如我为什么要使用一个线程?我可能用线程去跑一个简单上报的任务。如果有线程跑,就涉及到了线程的切换。那我在自己的线程里面,起一个协程去跑,即不用涉及系统的资源切换,又不会阻碍我主线程的任务。
niubee1
2021-12-13 15:19:38 +08:00
协程主要针对的场景是 IO 阻塞的时候能够有轻量高效的处理大批量并发任务。对于大量并发的 CPU 开销(运算)来说,协程毫无用处,因为协程并不能协调 CPU 资源,比如控制 ffmpeg 压缩视频这事,你用协程就没办法,因为 CPU 核就这么几个,你并发上万个协程也没法变出更多的 CPU 资源出来,反而会因为过多的切换而更慢。
cloud107202
2021-12-13 15:19:53 +08:00
协程适用于 IO 密集场景,CPU 密集场景的并行还是只能靠线程来 比如 folk-join pool + work stealing
协程还有个好处是结构化并发,代码可以线性书写,类似写同步逻辑一样


去补补基础好不?你这 rust 部分听说的也太对
ch2
2021-12-13 15:20:19 +08:00
@kingofzihua #4 为了解决这个场景下的问题:一个任务按先后顺序可以拆解成很多个子任务,每个子任务占用 CPU 的时间又非常短,运行不了几个微秒就主动让出 CPU 了。当同时存在数以万计的子任务的时候,用线程来解决此类问题会造成 CPU 一直在忙于切换线程,真正执行任务的时间片反而成了次要的占比。
协程并不是解决这种场景下的问题的:任务本来就是 CPU 密集型的,每个子任务都在争抢 CPU ,用于切换线程的损耗可以忽略不计。
cwcc
2021-12-13 15:20:25 +08:00
举个不恰当的例子,你是个打工人,你每天工作 8 小时,要做的事情有编译程序 A 、编译程序 B 、帮老板端茶倒水、收发邮件。

你相当于一个线程(或进程),老板交给你的工作相当于系统分配线程的任务。

而协程就是,你自己怎么去更高效完成自己的任务。如果没有协程,就相当于“编译 A->编译 B->帮老板端茶倒水->收发邮件”,而协程就相当于“编译 A 开始->跑去给老板倒水->收发邮件->编译 B 开始->编译 A 结束->编译 B 结束”,可以节省你大量你坐在电脑前但是没有实际工作的时间去做其他事情。(对应协程中就是,比如遇到 HTTP API 请求,需要 0.5 秒,可以让这个进程继续先干别的,请求后回来继续当前处理完 HTTP API 请求的上下文)。

和线程的区别?多协程可以有效利用单核心计算,避免过多的 IO 等待,多进程(线程)可以有效利用多核心计算,避免单核负载过高,不是一回事。
kingofzihua
2021-12-13 15:23:46 +08:00
@cloud107202 需要补的是什么基础?大佬给个方向?
kingofzihua
2021-12-13 15:26:09 +08:00
@ch2 按照我理解,比如需要读取文件,磁盘 IO 会比较慢,系统就会挂起当前线程,然后切换其他线程,你如果用协程,系统调用还是操作系统给你切换到其他线程了,协程的意义在哪里呢?
kingofzihua
2021-12-13 15:27:56 +08:00
@crazywhalecc 这个东西取决于你要做的事情吧,比如网络是非阻塞的 IO ,这时候你可以等待,然后做其他的事,但是 java 没用协程,NIO 也一样高性能啊。
Juszoe
2021-12-13 15:31:03 +08:00
简单来说,就是把线程切换的控制权从操作系统转移到应用程序,操作系统切一次线程代价不小
anytk
2021-12-13 15:31:09 +08:00
1. 协程是用户自己调度,切换开销堪比函数调用,比线程轻量
2. 协程可以对逻辑解耦简化,异步操作“同步”化,比如解决 callback hell

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/821871

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX