朱涛 · Kotlin 编程第一课
朱涛
Google 认证的 Kotlin、Android 开发者专家,博客“Kotlin Jetpack 实战”作者
6717 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 50 讲
朱涛 · Kotlin 编程第一课
15
15
1.0x
00:00/00:00
登录|注册

22 | 并发:协程不需要处理同步吗?

你好,我是朱涛。今天我们来讲讲协程的并发。
在大型软件的架构当中,并发也是一个不可避免的问题。然而,在传统的 Java 编程当中,并发却是个令人生畏的话题。因为 Java 的线程模型、内存模型、同步机制太复杂了,而当复杂的业务逻辑与复杂的并发模型混合在一起的时候,情况就更糟糕了!如果你用 Java 做过中大型软件,对此一定会深有体会。
我们都知道,Kotlin 的协程仍然是基于线程运行的。但是,经过一层封装以后,Kotlin 协程面对并发问题的时候,它的处理手段其实跟 Java 就大不一样。所以这节课,我们就来看看协程在并发问题上的处理,一起来探究下 Kotlin 协程的并发思路,从而真正解决并发的难题。

协程与并发

在 Java 世界里,并发往往需要多个线程一起工作,而多线程往往就会有共享的状态,这时候程序就要处理同步问题了。很多初学者在这一步,都会把协程与线程的概念混淆在一起。比如你可以来看看下面这段代码,你觉得有多线程同步的问题吗?
// 代码段1
fun main() = runBlocking {
var i = 0
// Default 线程池
launch(Dispatchers.Default) {
repeat(1000) {
i++
}
}
delay(1000L)
println("i = $i")
}
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Kotlin协程在处理并发问题上具有独特的特点和思路。本文深入探讨了协程的并发处理,重点介绍了在Kotlin中实现单线程并发、使用Mutex进行非阻塞式同步以及利用Actor模型实现多线程同步的方法。通过代码示例和详细解释,读者可以快速了解协程在处理并发问题时的灵活性和高效性。文章强调了协程的挂起、恢复和非阻塞特点,使得处理并发问题时可以采用更宽泛的思路,如单线程并发。同时,文章还提到了Kotlin官方对Actor API进行重构的计划,展示了协程技术的不断发展和完善。对于想要深入了解协程并发处理的读者,本文具有很高的参考价值。 总结:本文深入探讨了Kotlin协程在处理并发问题上的独特特点和思路,重点介绍了单线程并发、使用Mutex进行非阻塞式同步以及利用Actor模型实现多线程同步的方法。通过代码示例和详细解释,读者可以快速了解协程在处理并发问题时的灵活性和高效性。同时,文章还展示了Kotlin官方对Actor API进行重构的计划,彰显了协程技术的不断发展和完善。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《朱涛 · Kotlin 编程第一课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(12)

  • 最新
  • 精选
  • louc
    对于单线程并发,要提一个不同观点,在实际项目中delay这种延时任务往往是io操作,我做了一个测试,把这里delay替换为file.readText去读一个10M的文件,那个三个协程都用同一个mySingleDispatcher的话其实是串行执行的,并没与起到优化并行的效果,所以如果要说协程的优越性,这里还是得使用IO线程池既Dispatcher.IO。这样可以把多IO任务同时启动,达到并行优化,否则,同一个线程,协程无法并行,时间消耗是三个IO动作之和

    作者回复: 其实,主要还是因为用了Java底层的阻塞式IO。不可否认的是,现实生活中,符合条件的非阻塞场景并不多。

    2022-04-25
    3
    9
  • êwěn
    mutex是挂起函数,那么它存在竞争的话是支持协程挂起,意味着底层线程资源可以复用,比起Java的线程并不会浪费多余的系统资源

    作者回复: 没错

    2022-03-09
    7
  • 神秘嘉Bin
    大眼看了下Mutex的源码,看起来很像AQS的实现。 这里等待的节点可能不是自旋等待,应该是把CallBack塞到了队列,前面节点释放锁,后续节点竞争然后执行CallBack。 因为没有自旋等待,所以不会阻塞线程,效率自然会高。

    作者回复: 是的,可以这么理解。

    2022-03-09
    4
  • Allen
    我认为 Mutex 比 JDK 的锁性能更好,主要有两个原因: 1. Mudex 挂起的是协程,协程被挂起,线程并不会被阻塞。而 JDK 锁的都是线程,线程会被阻塞。 2. 挂起不浪费系统资源,而阻塞由于会管理锁队列等,会浪费更多的系统资源。 本质上来说,这个效率和资源是由挂起函数的实现方式决定的,而这也是协程的核心。

    作者回复: 是的,可以这么理解。

    2022-03-09
    3
  • 杨小妞
    并发场景:多线程执行耗时任务(例如网络请求)。如果用“单线程并发”的概念去实现,应该是无法达到目的。

    作者回复: 主要是看任务是“阻塞型”,还是“非阻塞型”。如果是阻塞型,则无法:单线程并发。

    2022-03-26
    2
  • 辉哥
    大佬,问个问题,Mutex是非阻塞的,那它是如何防止共享变量不会同时被多个线程修改的

    作者回复: 其实,它的流程和普通锁是差不多的,区别在于,普通的锁在获取不到执行权限的时候,会阻塞,而Mutex则是挂起。

    2022-03-09
    2
    2
  • 白乾涛
    老师,我觉得"单线程并发"是一个伪概念,他只是看起来像是并发代码,实际上,这种"单线程并发"的代码用 Java 的 CallBack 也是可以实现的 --- 比如借助 LockSupport

    作者回复: 可以这么理解,协程的好处在于,并发概念与线程之间完全解耦了,同样的代码改动一个参数就能实现单线程并发。案例中之所以可以实现单线程并发,本质还是因为非阻塞。

    2022-03-18
    2
    1
  • 神秘嘉Bin
    大眼看了下Mutex的实现,看上去很像AQS的实现;可能是基于AQS进行了一波改造吧尝试加锁成功就resume;

    作者回复: 嗯,其中有挂起和恢复。

    2022-03-09
    1
  • 杨小妞
    业务场景:生产消费者。如果希望用协程来控制消费者的个数,除了自定义Dispatchs以外,还有什么其他好的方式吗?

    作者回复: 多个消费者不一定要多个线程,我们使用多个协程也可以的。

    2022-03-26
  • 白乾涛
    这个问题和"协程对线程性能更好吗"类似,我觉得答案都是否定的,因为这么比较不公平。 如果这么问:大神用 Kotlin 的 Mutex 写的代码,和大神用 JDK 的锁写的代码,相比,性能更好吗?

    作者回复: 确实没有绝对的优劣,要分场景讨论才行。

    2022-03-18
收起评论
显示
设置
留言
12
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部