Kotlin 的协程实现的意义是什么呢?

2020-03-20 23:30:14 +08:00
 insomnia1232

看了 kotlin 的协程实现,感觉就是线程调度库,换句话说就是伪协程,那和 Rxjava 这种东西的区别在哪呢?是切换效率更高,写起来更简洁吗?还是就因为是官方钦定的

7065 次点击
所在节点    Kotlin
31 条回复
LosLord
2020-03-20 23:40:55 +08:00
为了让 Callback 看起来不反人类
aguesuka
2020-03-21 00:06:07 +08:00
java:
read(result-> dosomething());

kotlin:
val result = read();
doSomething();

java 没法在语言级别做到这样写异步代码
winterbells
2020-03-21 00:15:44 +08:00
用了 kotlin 后,rxjava 库已经移除了
val resp = getFromServer()
resp.xxx

不需要走 callback 了,减少嵌套
xcstream
2020-03-21 00:57:42 +08:00
代码上减少嵌套
Kotlin 还可以转译成非 java 的语言
Tyanboot
2020-03-21 03:11:18 +08:00
如果这个算伪协程的话, 那真协程应该是什么样子, 或者说具有什么特性才算是真协程呢.
abcbuzhiming
2020-03-21 08:00:54 +08:00
@Tyanboot 协程的定义是“用户级别的多线程”,而传统的“多线程”是有内核态参与的系统级别实现的多线程,这种实现的线程的建立成本不低,因为内核资源宝贵,并且切换线程的时候有所谓的线程上下文切换开销,用户态内核态切换开销。而协程只在用户态,所以新建协程的成本很低,一台机器上可以建远远比线程上限数量高的多的协程,并且因为只在用户态,协程的切换成本也很低。虽然协程的任务最终还是交给系统线程完成的,但是协程的发明是语言技术进步而对内核技术的一次瘦身,多线程技术有内核态参与这个问题本质上是早期的语言性能不够,为了性能,让内核具备了多线程调度的能力,提供了一种通用的多线程编程模型,且性能不错,但是随着时间语言技术开始进步,慢慢的就有人觉得内核参与的线程成本太高了,而用户态这边的硬件和软件资源突飞猛进,有了超越内核态的可能性,于是就有人希望把多线程再次移动回用户态,这本质是技术发展的一种历史轮回
PDX
2020-03-21 08:40:59 +08:00
怎么看出是“伪协程”的??
reus
2020-03-21 08:52:41 +08:00
@abcbuzhiming 你对协程的定义是错误的,协程就是“协作式调度的过程”,和它相对的是“抢占式调度的过程”,和用户态内核态没有关系。协作式调度是早于抢占式调度出现的,不存在什么“协程的发明”。基于时钟中断的操作系统线程,在内核看来,也是协作式的,只不过在用户看来是抢占式。
用户态线程就是用户态线程,不要和协程混为一谈。
micean
2020-03-21 09:28:28 +08:00
1. 让代码看得更舒服
2. 异常处理更舒服
3. 逻辑处理更舒服

java 的 vertx 这么写异步

```
Promise.promise(p ->
异步 A(p)
).compose(结果 A -> {
if(逻辑 A){
return Promise.promise(p -> 异步 B(结果 A))
}else{
return Promise.promise(p -> 异步 C(结果 A)).compose(结果 B -> Promise.promise(p -> 异步 D(结果 B)))
}
}).map(结果 C ->
结果 D
).setHandler(最终结果 -> {
if(没有异常){
返回结果
}else{
处理异常
}
})
```

同步代码这么写

```
try{
结果 A = 异步 A()

if(逻辑 A){
结果 C = 异步 B(结果 A)
}else{
结果 B = 异步 C(结果 A)
结果 C = 异步 D(结果 B)
}

return (结果 D)结果 C
}catch(e){
处理异常
}
```
wancaibida
2020-03-21 09:35:15 +08:00
为了以更直观的方式写异步
hyyou2010
2020-03-21 09:51:54 +08:00
我没有读过协程的内部实现,我的理解是:启动协程时可以新启线程,但是协程切换可以在同一个线程内,且仅在用户态完成,这就算真协程,非常高效,这就比需要切换线程的方案强。
crella
2020-03-21 09:54:10 +08:00
如果我理解得没有错的话,ruby 的 Fiber 也是伪协程,只是方便不同函数的让出 /切换。在不支持 fork 的系统上,支持并发的只有 Thread.new 。
newmlp
2020-03-21 10:05:56 +08:00
协程就是在用户空间实现的线程啊,不然你觉得协程是啥
sukaidev
2020-03-21 10:19:43 +08:00
kotlin 既然是 JVM 语言 自然跳脱不出 JVM
协程就是为了能够像平时写同步代码一样写异步代码
如果说 rxjava 是方便的线程切换 那协程就是感觉不到线程在切换 甚至不需要切换线程同样做到了“异步”
janxin
2020-03-21 10:41:02 +08:00
自然是为了不反人类…这是协程存在的意义之一
codehz
2020-03-21 11:48:23 +08:00
协程的意义是可以以一致的方法写同步或者异步的调用,而不需要大规模改变写法(比如变成一堆回调)
准确说它并没有提升性能的意思在里面,也不是什么银弹,不可能把原本做不到异步的东西变成可以异步的,比如 linux 原本没有提供不开线程的异步文件 io,那你也不可能通过协程变成可以不开额外线程的异步读写文件
因此从这个意义上说,协程就是语言提供的一种机制,简化异步代码的编写
关于和线程的对比,其实是异步 vs 同步的对比,然后协程可以让异步代码变得看起来像同步的一样,仅此而已
更一般地说,协程也未必真的要为了异步,也可以用作更一般化的逻辑解构,不过那就是另一个故事了
hhhsuan
2020-03-21 12:12:43 +08:00
如果不用切换线程就实现任务的调度那就是真协程,但 kotlin 给我的感觉是任务的调度还是通过线程切换完成的。
wanglufei
2020-03-21 12:25:04 +08:00
callback 的语法糖
qiyuey
2020-03-21 12:38:40 +08:00
@reus 现阶段协程可以理解为:用户态协作式线程;广义和狭义的区别,没必要抠字眼
qiyuey
2020-03-21 12:41:16 +08:00
可以从多个层面理解:
1、是否已经清楚 阻塞 和 非阻塞 的区别
2、是否已经清楚 Callback 的问题
3、是否已经清楚 Reactive 和 Coroutines 的区别
这三个问题是逐层递进的,需要一个一个理解

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

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

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

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

© 2021 V2EX