大部分语言的协程都是基于 epoll/select 机制,由于 epoll/select 只能处理 IO 问题,所以导致大部分语言的协程也只能处理 IO 问题
而 go 语言的协程可以在任何情况下使用,是真正意义上的协程,底层是通过汇编指令 pop/push 保存上下文
以上理解正确吗?
1
nightwitch 2023-08-10 13:31:42 +08:00 via Android 2
把协程的实现放到库来做还是放到语言特性里只是语言设计者的偏好问题。协程和 epoll 也是正交的关系,没什么基于不基于的。
|
2
thinkershare 2023-08-10 13:34:09 +08:00
因为协程并不是什么先进值得被其它语言吸收的好东西,纯粹是语言创建者的个人偏好。
|
3
coderxy 2023-08-10 13:39:25 +08:00 1
因为现在流行的几个语言里面,就属 go 诞生的最晚,其它语言有一定的历史包袱。
|
4
tulongtou 2023-08-10 13:43:16 +08:00
Java 也原生支持了
|
5
emSaVya 2023-08-10 13:43:18 +08:00 8
你可能需要重新理解协程的概念。
另外应该是 2015 年前后 大批程序设计语言都上了 coroutine, 比如 c# js python 。什么概念时髦了就上什么。 c++ coroutine 讨论了得有几十年了, 现在 c20 也加上了。 |
6
duke807 2023-08-10 13:48:11 +08:00 via Android
各语言协程的底层都是通过汇编指令 pop/push 保存上下文
|
7
lovelylain 2023-08-10 13:52:06 +08:00 via Android
@duke807 async/await 这种是状态机
|
8
agagega 2023-08-10 15:24:19 +08:00 via iPhone 1
协程和用户态线程是不同的东西,只是 go 利用特殊设计在后者实现了前者的要达到的效果。Swift 的并发支持也有点异曲同工之妙
|
9
sunny1688 2023-08-10 16:02:40 +08:00 2
yield 就是协程,很多语言都支持协程的,只不过没有语言层面实现调度器(运行时)
|
10
touchmii 2023-08-10 17:03:34 +08:00
就一个 runtime 的事情, 想支持啥特性都可以, 至于 go 为什么要放到语言特性中来自然是要宣传造势, 这是它最显著的特点.
|
11
kenvix 2023-08-10 17:48:39 +08:00
先问是不是,再问为什么。
|
12
GeekGao 2023-08-10 17:54:54 +08:00
x y problem
|
13
oldshensheep 2023-08-10 18:07:13 +08:00
golang 的协程有两种抢占式和协作式,抢占式类似于 Java 的虚拟线程,协作式类似于 yield
支持类似于 Golang 的抢占式的协程的语言有 Java ,其他的语言好像不怎么支持 |
14
nuk 2023-08-10 19:55:29 +08:00 4
golang 从来都没有协程,goroutine 本质上是 M:N 的用户线程。
官方的说法: A goroutine is a lightweight thread managed by the Go runtime. |
15
WebKit 2023-08-10 20:03:24 +08:00 via Android
Kotlin 也支持
|
16
ravenl 2023-08-10 20:08:43 +08:00
go 的协程还没出啊
https://research.swtch.com/coro |
17
AItsuki 2023-08-10 21:05:42 +08:00 4
goroutine 确实不是协程。协程最关键的一点是非抢占式调度,可以显式的挂起和恢复,而不是阻塞。
|
18
ikas 2023-08-10 22:20:47 +08:00
不正确
|
19
wangritian 2023-08-11 01:42:40 +08:00
不懂,但 goroutine+channel 做 IO 并发真的超爽
|
20
lightjiao 2023-08-11 04:19:37 +08:00 via iPhone 1
强烈建议了解一下 async/await
https://www.zhihu.com/question/65647171/answer/233495694 |
21
yulon 2023-08-11 07:16:07 +08:00
你完全说反了,Go 的底层就是 Epoll/IOCP/Kqueue ,你就算不使用网络功能,它默认就是用的 net poll ,因为它就是发明来解决网络问题的语言😅
|
22
holulu 2023-08-11 08:28:39 +08:00
Go 诞生的目的是为了提升编写多核及网络应用的效率,其特性的设计肯定就围绕这个目标的。
|
23
hankai17 2023-08-11 08:32:51 +08:00
我认为 任何语言都可以实现自己的协程
但是很少有像 go 那样 自带协程调度器 还有我认为 抢占/非抢占 区别就是主动/非主动的'yeild'当前上下文 对于协程实现来说 不是特别难 所以我认为 原生支持协程 原生就意味着 有协程调度器 |
24
lysS 2023-08-11 09:15:22 +08:00
go 的调度就是依赖系统的异步模型啊,这样可以在 go 里面用同步代码写异步逻辑,而不用一堆回调;像文件 io 没有异步模型,go runtime 只有锁定 M
|
25
tyrantZhao 2023-08-11 09:43:10 +08:00 1
只有 go 自带调度器了
|
26
weishao2011 2023-08-11 10:07:36 +08:00
1 、epoll/select:确实,很多基于协程的异步 I/O 库利用了 epoll (在 Linux 上)或 select 来进行非阻塞 I/O 操作,以支持高并发。这些机制主要处理 I/O 问题,如网络通信、文件读写等。
2 、大部分语言的协程只能处理 IO 问题:这不完全正确。协程的本质是一种轻量级的线程抽象,用于支持高效地切换执行上下文。而是否主要用于 I/O 取决于其使用场景和设计目的。有些系统和库的确重点强调了 I/O ,但协程本身的设计和实现并不局限于此。 |
27
githmb 2023-08-11 10:18:13 +08:00
那 Rust 就不算原生支持了吗
|
28
Huelse 2023-08-11 10:22:11 +08:00
实际上都是跑在系统线程上的,只是调度方式不同罢了。
|
29
cosmain 2023-08-11 10:34:05 +08:00 1
|
30
cosmain 2023-08-11 10:40:26 +08:00
IO 多路复用需要系统底层提供支持来实现一个线程中监控多个文件描述符的 IO 事件,但是通常你去真正读写的时候,还是会打开新的线程。
协程是一个语言层面的抽象,只需要语言提供库和特性,和系统底层无关,通常是用户态的“技巧”,旨在在一个线程中处理多个“task”,达到减少内核线程存储、上下文切换等开销。 |
31
mmdsun 2023-08-11 11:36:51 +08:00
正意义上的协程??到现在协程本身没有一个统一的定义吧,而是一个广泛的概念。
https://en.wikipedia.org/wiki/Coroutine 其实用汇编也能做到的,不一定需要基于 epoll/select 机制。 而且这个也不是异步 IO 。IOCP 、Linux 5.1 以后的 io_uring 了解下。 协程和 IO 多路复用关联不是很强。通常说协程是一种编写并发代码的方式,可以在某些点暂停和恢复它们的执行不阻塞主线程。 你用 goto 、lablel 跳转+状体机写,也能算 coroutine 吧?( stackless coroutine ) |
32
chesha1 2023-08-11 13:24:04 +08:00
C++20 也有协程了,也是任何条件下可以用的函数
|
33
wanguorui123 2023-08-11 13:27:33 +08:00
协程、虚拟线程、事件队列,实现目的都类似
|
34
wonderblank 2023-08-11 14:37:28 +08:00
> 大部分语言的协程都是基于 epoll/select 机制,由于 epoll/select 只能处理 IO 问题,所以导致大部分语言的协程也只能处理 IO 问题
不正确,协程和 epoll 不是一个东西,也不是说基于什么。你可以理解为协程是香蕉,epoll 是体重。epoll / select / kqueue 是多路复用的实现方案而已。可以配合协程使用。 > 而 go 语言的协程可以在任何情况下使用,是真正意义上的协程,底层是通过汇编指令 pop/push 保存上下文 不正确,首先没办法定义`真正意义上的协程`是什么,以及底层基本上都一样。 > 以上理解正确吗? 全部不正确 基本上可以用任何语言实现协程。 @wanguorui123 > 协程、虚拟线程、事件队列,实现目的都类似 不正确。设计他们,以及背后的原因都各不相同。对于特定的问题没有银弹,所以出现了很多方案。 |
36
oxromantic 2023-08-11 14:45:36 +08:00
lua 是在 bytecode 层面的协程,用的 longjmp ,完全不用线程等机制
|
37
zjsxwc 2023-08-11 14:59:20 +08:00
完整的协程,php8.1 也有
https://www.v2ex.com/t/953310#reply0 |
38
vizee 2023-08-11 15:01:12 +08:00
先问是不是,再问为什么
|
39
wanguorui123 2023-08-11 16:00:03 +08:00
@wonderblank 设计目的都是为了高吞吐量,榨干系统性能
|
40
luoqeng 2023-08-11 16:29:20 +08:00
问题的关键应该是协程调度器实现
其他语言库一般用来处理网络 io ,只是利用 epoll/select 来实现调度器,Go 没有依赖 io 复用来实现调度器 |
41
wetalk 2023-08-11 16:34:26 +08:00
回到线程的定义:操作系统能够进行运算调度的最小单位。协程不是必须的
|
42
wonderblank 2023-08-11 17:41:15 +08:00
|
43
charlie21 2023-08-11 17:46:36 +08:00
Golang 采用的 CSP 模型和 Erlang 的 Actor 模型
https://zhuanlan.zhihu.com/p/27341488 |
44
julyclyde 2023-08-11 19:44:20 +08:00
能提出这种问题,说明思维方式有问题
|
45
bthulu 2023-08-12 16:33:46 +08:00
epoll 又不是什么牛逼机制, 纯属微软作死导致 epoll 在服务端一家独大. 你可以试试 iocp, 比 epoll 强多了, 偏偏支持的没几个.
|
46
inshua 2023-08-12 18:37:30 +08:00
erlang 早就有了,那几年 erlang 火了一阵,后来实在太非主流了用的就少了,但是设计思想传播出去了就有了一堆衍生,当然协程出现的更早,但是在并发领域用协程 erlang 应该算是早的
|