这里我想出个判断题,看看大家想的是不是一致的
相对于线程来说,假设有很多请求,假设是 Golang 语言
这里面是都是正确的吗?
1
hdbzsgm 2020-09-09 14:49:55 +08:00 2
不加场景的话 严格说都不对 协程可以提一句 降低上下文切换频次
|
2
misaka19000 2020-09-09 14:50:00 +08:00 2
以前是为了充分利用 CPU 资源(在现代操作系统出现之前);
现在是为了简化异步操作,提升程序员编写代码的简洁性; |
3
OwO233 2020-09-09 14:50:34 +08:00
https://www.zhihu.com/question/20511233
谷歌搜到了知乎的湖大,感觉很牛,尼康康。OwO |
4
misaka19000 2020-09-09 14:50:57 +08:00
|
5
caskeep 2020-09-09 14:52:40 +08:00 via iPhone
@misaka19000 #2 +1 切换到 go 就是为了异步处理省事好写...
|
6
ysc3839 2020-09-09 15:05:05 +08:00
感觉网上讨论“协程”更多是指有调度器的,单线程执行的协程。我自己没有接触过,并不太了解。
我自己最早接触协程是 Python 和 JavaScript 的 async fuction 和 generator,这里的协程是一种可以中途返回,后面再恢复执行的函数,现在 C++ 20 的协程也是属于这一类。 如果讨论是后面这种协程的话,那处理 IO 快不快、上下文开销大不大,完全取决于怎么实现的,用户可以用线程池+同步 IO 。 |
7
wysnylc 2020-09-09 15:23:54 +08:00
把多线程能解决的问题搞复杂,把多线程不能解决的问题解决掉
|
8
FutherAll 2020-09-09 15:32:17 +08:00
goroutine 就是减少频繁的线程上下文切换带来的 CPU 消耗吧,以及 goroutine 占用的内存空间更小。
G-P-M 模型,真正需要切换线程是在 M 的切换,G 的切换是 go 在用户态实现的调度器来做的,更像是一种用户态线程。 |
9
lambdaq 2020-09-09 15:40:06 +08:00
真正的作用,那就是处理能力分时啊。。
|
10
noe132 2020-09-09 15:54:57 +08:00 via Android 1
协程是单线程异步,你不需要处理锁的问题
|
11
keepeye 2020-09-09 16:28:04 +08:00
goroutine 是多线程协程,能并行的,跟别的语言的单线程协程还是有很大不同的
|
12
PiersSoCool OP 感谢大家。
感觉协程在 JS 来说可能语法上更加方便。 我可能看了一些奇怪的文章,说协程能提升 IO 速度搞得我十分困惑。我是觉得 IO 问题是多路复用解决的。 |
13
PiersSoCool OP 我感觉 go 的协程可以解决一些问题,创建 1000 个线程任务的代价和创建 1000 个协程任务(可能只有几个线程)的代价是不一样的,上下文大部分情况应该都是相同的,上下文切换次数也是不一样的。
|
14
zhangfeiwudi 2020-09-09 16:38:03 +08:00
协程上下文开销很少
协程占用资源很少 这两对的 在这两个的前提下 ,才有“协程处理高并发很快” 因为携程切换都是在用户态进行,所以速度很快,而且每次切换保留现场的资源很少 |
15
PDX 2020-09-09 16:42:39 +08:00 via iPhone
我觉得解决回调地狱是最大的作用
|
16
lbp0200 2020-09-09 16:48:37 +08:00
协程处理 IO 很快
一百万 IO 任务需要处理 用线程解决,同时只能启动 1000 个 用协程解决,同时只能启动 100000 个 你猜,最后哪种解决方案先完成,先完成的解决方案,算不算快? |
17
PiersSoCool OP @lbp0200 我觉得在这两个处理 IO 速度是一样的,Golang 里协程也是通过线程实现的,最后都要走到系统调用上,假设采取的都是同样的 IO 技术,无论到没到达系统 IO 瓶颈,速度都是一样的,甚至说,线程还能比协程快一些。以我的了解,像这种阻塞的系统调用,并发启动 100000 个协程 = 启动 启动 100000 个线程,会爆炸的。不知道是不是对的。
|
18
linw1995 2020-09-09 19:32:23 +08:00
1. 用协程也是有用到锁的时候
2. 协程减少了上下文切换的时间 3. 用起来更方便,可以控制每个协程的状态(有的实现例外) |
19
optional 2020-09-09 19:40:12 +08:00 via iPhone
减少线程的上下文切换。
|
20
JaguarJack 2020-09-09 21:26:06 +08:00 via iPhone
3 是重点 用户态的切换开销小
|
21
Aoang 2020-09-09 22:11:38 +08:00 via Android
@PiersSoCool 10w 协程不可能等同于 10w 线程。
IO 堵塞的时候,线程切换的开销多大?这还没提机器,创建线程的资源大小能和协程相比么… 如果不考虑多路复用,协程会吊打线程。实际应用中,因为多路复用会导致两者差异并不是非常大。 但是如果线程与线程之间需要传输资源…差距又会被拉很大。 而且线程是比协程复杂的多的…玩的不好……就不用说了 |
22
cmdOptionKana 2020-09-09 22:19:56 +08:00
@PiersSoCool 不对,Golang 只是在有需要的时候自动开线程以充分利用 CPU,协程与线程不是一比一,而是多比一。
|
23
Acoolda 2020-09-09 23:14:33 +08:00 via Android
就是合集利用 io 等待时间来执行其他任务,让 cpu 一直处于忙的状态
|
24
hakono 2020-09-09 23:31:00 +08:00 1
说个我的看法
我觉得只需要记住一点就行了: 协程不能改善计算密集型任务的执行效率,但却能极大改善大量需要 白 白 干 等 的任务(典型就是 IO 密集)的执行效率 其实在这里是有一个界限的,线程数量少的时候其实用多线程还是协程差别没那么大。但是当线程非常多,切换开销过大时,协程的优点才会显现,1,2,3,4 才会大致成立(比如大量 IO 请求) 其实对人类来说,协程才是我们最熟悉、用得最多的处理事情的逻辑。不如说大部分时候我们都是在用协程的思维在处理事情的。即便是对编程一无所知的大妈,平时做饭时都在用协程思维:在烤面包的空档去切菜做其他事情,而不是烤面包的时候就在那干等面包烤完。这就是典型的协程思维。 烤面包需要好几分钟,这好几分钟是白白干等的,相当于做 IO 请求( IO 请求和 cpu 处理速度相比是非常慢的)。这 IO 请求的空档 cpu 完全能去做其他事情而不是在那干等。 所以理解到这层之后,就会发现我们生活处处都是在用协程做事。然后什么情况协程比线程更好也能比较好判断了 |
25
hakono 2020-09-09 23:31:55 +08:00
对了,追加个 go 协程相关的,这个上面已经有人说了:
讨论协程要区分一般意义上说的协程 和 go 语言的协程( goroutines ) 一般意义上单线程里跑的协程是无法利用多个核心的资源的(毕竟开再多协程都是在一个线程里跑,没法利用多个核心)。解决办法就是开几个线程,把协程分配到这些线程里执行,这样就能完全利用 cpu 了 go 语言的协程就是后者,在协程的基础上自带调度器,会根据需求创建多个线程然后把协程分配到不同线程里运行,从而利用多个核心。写代码的人根本不用去纠结该开几个线程,每个协程该怎么调度 |
26
reus 2020-09-10 04:08:53 +08:00
goroutine 又不是协程。
|
27
12101111 2020-09-10 09:41:20 +08:00
1.协程处理 IO 很快
协程不会让 IO 操作变快,但是可以在等待 IO 操作时执行其他协程,也就是提高了吞吐量 2.协程处理高并发很快 同 1, 吞吐量大了才能处理高并发 3.协程上下文开销很少 相较于 fork join 模式,线程池+有栈协程的开销更小,但是 Rust 的无栈协程才是无开销的模式 创建线程需要操作系统分配完整的栈+TCB, 而创建有栈协程只需要分配较小的栈+运行时自己调度,无栈协程在编译时直接变成状态机,运行时建立这个状态机就一直执行下去了,不需要分配栈. 4.协程占用资源很少 有栈协程会分配一块内存作为栈,比线程省资源 |
28
chaleaoch 2020-09-10 14:02:50 +08:00
234 吧.
|