【问题标题】:Kotlin: Skipping CoroutinesKotlin:跳过协程
【发布时间】:2017-09-16 23:10:19
【问题描述】:

我在我的演示 android 应用程序中使用 Kotlin 和 Coroutines。

这是我所拥有的:

fun testCoroutine3() = runBlocking {
    var num = 0
    val jobs = List(10_000) { // create a lot of coroutines and list their jobs.
        launch(CommonPool) {
            delay(1000L)
            println(num++)
        }
    }

    for(job in jobs) {
        job.join() //wait for all jobs to finish
    }
    println("FINAL RESULT $num")
}

基本上,我正在创建一个包含 10,000 个协程的列表,它们等待 1 秒并打印一个数字,然后将其递增。

然后,当所有作业都完成后,我会打印最终结果。

(本演示取自GitHub Documentation

现在我的大部分测试运行良好,所有协程几乎同时运行,我的最终结果是 10000

但在极少数情况下,我得到的最终结果是 9,999

例如,当我将数字增加到 50,000 时,这一点变得更加明显:

当有很多协程时,Kotlin 是否可能会跳过一些协程?在 50,000 上,看起来它跳过了 2

或者这里发生了什么其他事情?

【问题讨论】:

    标签: android kotlin coroutine


    【解决方案1】:

    num++ 包含两个操作:tmp = num + 1num = tmp。在处理像您的示例这样的多线程时,有些操作可能会覆盖另一个线程的结果,从而导致像您的示例这样的情况。

    如果您想了解更多信息,请研究“竞争条件”,其中最终结果取决于两个独立进程之间的“竞争”。

    【讨论】:

    • 啊,这很有道理!知道我可以使用哪种方法来确保我得到最终结果 = 10,000?除了做jobs.count
    • 保证对变量的访问同步或使用Atomic* 类确保每个操作最终都被注册的唯一方法。
    • @Youssef 通常,您会尽量避免使用任何共享的可变状态。这也将消除这个问题。
    • @marstran 我同意设计应该远离这个,但如果我们想使用它,我发现我可以使用 AtomicInteger() 代替。
    猜你喜欢
    • 2021-06-27
    • 1970-01-01
    • 2019-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-19
    • 2019-12-25
    • 2020-02-17
    相关资源
    最近更新 更多