本例中,我们模拟了这样一个场景,使用自定义的作用域 scope 短时间内开启 1000 个协程,协程中每次把 count 自增 1 打印数据。如果最终打印的数据是 1000 那么说明不存在并发,如果打印的数据小于 1000,那么说明协程中也存在如 java 一样的并发问题。
- 日志
这里只发出最后一部分的日志:
696
695
694
693
692
691
690
703
702
- 结论
日志打印最终验证协程中也存在并发性的问题,那么后面的章节我们就拿出我们的协程解决方案吧。
模拟案例扩展
我们将本例中的代码做一个扩展,在concurrent方法尾部加一个1s的延时
- 代码
image
- 输出日志
999
1000
978
995
994
993
992
991
1000
- 结论
当最后一个协程执行完成时可以计算出1000这个正确结果但是打印的中间值顺序却是错乱的(这一点和java不一样),但是我们在业务代码中却没有办法获取这个正确结果产生的时间,所以我们依然要处理并发问题
解决并发的方法
解决并发的问题既可以使用 java 中的部分方式,也可以使用 kotlin 自有的方式。协程自有的处理方法适用性更广一些。
java 方式解决
如果我们想使用java的方式解决并发,那么我们可以尝试让协程运行在单线程中,也可以尝试使用Atomic方式
单线程解决方法
我们将 模拟并发章节的代码进行一些改动试试:
- 代码
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)
}
}
}
- 日志
994
线程id:1
995
线程id:1
996
线程id:1
997
线程id:1
998
线程id:1
999
线程id:1
1000
- 结论
本例代码中因为launch始终运行在单线程中所以最终输出count==1000,中间值的顺序也没有错乱
使用Atomic方式解决
上一小节中我们的代码始终运行在单线程中,所以最终输出正确结果,那么如果我们的代码不允许在单线程中有没有解决方法呢,答案当然是有, Atomic机制即可解决。
试想一下如果我们把上面的代码scope.launch 改为launch(Dispatchers.Default) ,那么线程就变成了运行在多线程中了,此时输出的最终结果一定不会是我们想要的(我已经帮你试过了,就不贴代码和日志了)
那么我们可以尝试用Atomic方式解决这个问题
- 代码
suspend fun concurrent() {
var count =AtomicInteger(0)
coroutineScope {
repeat(10000) {//重复1000次,每次开启一个协程,count自增1
launch(Dispatchers.Default) {
count.incrementAndGet()
println(“计算中间值$count”)
}
}
}
delay(1000)
println(“计算结果:$count”)
}
- 日志
计算结果:10000
- 结论
虽然最终输出结果是正确的
但是对于负责的状态Atomic明显是处理不了的,负责的状态可以考虑后面要讲的Mutex方式
kotlin 方式解决
互斥
kotlin 为我们提供了Mutex实现线程安全,Mutex通俗点来说就是kotlin的锁,和java 的synchronized和RecentLock对应。
使用mutex.withLock {*} 即可实现数据的同步
看代码:
- 代码
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-tnWHIkLz-1715784292756)]
[外链图片转存中…(img-X5rYHOfu-1715784292759)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!