kotlin 协程也有并发?

本例中,我们模拟了这样一个场景,使用自定义的作用域 scope 短时间内开启 1000 个协程,协程中每次把 count 自增 1 打印数据。如果最终打印的数据是 1000 那么说明不存在并发,如果打印的数据小于 1000,那么说明协程中也存在如 java 一样的并发问题。

  1. 日志

这里只发出最后一部分的日志:

696

695

694

693

692

691

690

703

702

  1. 结论

日志打印最终验证协程中也存在并发性的问题,那么后面的章节我们就拿出我们的协程解决方案吧。

模拟案例扩展

我们将本例中的代码做一个扩展,在concurrent方法尾部加一个1s的延时

  1. 代码

image

  1. 输出日志

999

1000

978

995

994

993

992

991

1000

  1. 结论

当最后一个协程执行完成时可以计算出1000这个正确结果但是打印的中间值顺序却是错乱的(这一点和java不一样),但是我们在业务代码中却没有办法获取这个正确结果产生的时间,所以我们依然要处理并发问题

解决并发的方法


解决并发的问题既可以使用 java 中的部分方式,也可以使用 kotlin 自有的方式。协程自有的处理方法适用性更广一些。

java 方式解决

如果我们想使用java的方式解决并发,那么我们可以尝试让协程运行在单线程中,也可以尝试使用Atomic方式

单线程解决方法

我们将 模拟并发章节的代码进行一些改动试试:

  1. 代码

fun concurrent() {

val scope = CoroutineScope(Dispatchers.Unconfined)//创建协程作用域,使用Unconfined,这样在协程被挂起前都不会改变线程,也就是说协程始终运行在单线程中

var count = 0

repeat(1000) {//重复1000次,每次开启一个协程,count自增1

scope.launch {

println(“线程id:${Thread.currentThread().id}”)//这个线程始终不会变,除非你在这里挂起

count++

println(count)

}

}

}

  1. 日志

994

线程id:1

995

线程id:1

996

线程id:1

997

线程id:1

998

线程id:1

999

线程id:1

1000

  1. 结论

本例代码中因为launch始终运行在单线程中所以最终输出count==1000,中间值的顺序也没有错乱

使用Atomic方式解决

上一小节中我们的代码始终运行在单线程中,所以最终输出正确结果,那么如果我们的代码不允许在单线程中有没有解决方法呢,答案当然是有, Atomic机制即可解决。

试想一下如果我们把上面的代码scope.launch 改为launch(Dispatchers.Default) ,那么线程就变成了运行在多线程中了,此时输出的最终结果一定不会是我们想要的(我已经帮你试过了,就不贴代码和日志了)

那么我们可以尝试用Atomic方式解决这个问题

  1. 代码

suspend fun concurrent() {

var count =AtomicInteger(0)

coroutineScope {

repeat(10000) {//重复1000次,每次开启一个协程,count自增1

launch(Dispatchers.Default) {

count.incrementAndGet()

println(“计算中间值$count”)

}

}

}

delay(1000)

println(“计算结果:$count”)

}

  1. 日志

计算结果:10000

  1. 结论

虽然最终输出结果是正确的

但是对于负责的状态Atomic明显是处理不了的,负责的状态可以考虑后面要讲的Mutex方式

kotlin 方式解决

互斥

kotlin 为我们提供了Mutex实现线程安全,Mutex通俗点来说就是kotlin的锁,和java 的synchronized和RecentLock对应。

使用mutex.withLock {*} 即可实现数据的同步

看代码:

  1. 代码

val mutex = Mutex()

suspend fun concurrent() {

var count =0

coroutineScope {

repeat(10000) {//重复1000次,每次开启一个协程,count自增1

launch(Dispatchers.Default) {

结语

  • 现在随着短视频,抖音,快手的流行NDK模块开发也显得越发重要,需要这块人才的企业也越来越多,随之学习这块的人也变多了,音视频的开发,往往是比较难的,而这个比较难的技术就是NDK里面的技术。
  • 音视频/高清大图片/人工智能/直播/抖音等等这年与用户最紧密,与我们生活最相关的技术一直都在寻找最终的技术落地平台,以前是windows系统,而现在则是移动系统了,移动系统中又是以Android占比绝大部分为前提,所以AndroidNDK技术已经是我们必备技能了。
  • 要学习好NDK,其中的关于C/C++,jni,Linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且
  • OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
,Linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且

  • OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。

[外链图片转存中…(img-foChAeTN-1715573875605)]

[外链图片转存中…(img-2epvrPJd-1715573875609)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值