【问题标题】:Second corutine is never executed第二个协程永远不会执行
【发布时间】:2022-08-18 15:39:10
【问题描述】:

我在另一个里面有两个协程,假设两个内部协程都将异步执行,但这并没有发生。第二个等到第一个完成。 这是我的代码:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {
     var flag = false
     override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_main)

          runBlocking {
                launch {
                    printOne()
                }
                launch {
                    printTwo()
                }
          }
    }

    suspend fun printOne() {
         while (flag == false)
             Log.e(\"log\", \"111111\")
    }

    suspend fun printTwo() {
         Log.e(\"log\", \"222222\")
         Log.e(\"log\", \"222222\")
         Log.e(\"log\", \"222222\")
         Log.e(\"log\", \"222222\")
         flag = true
   }
}

我假设第一个 launch{} 中的代码将在线程中与第二个 launch{} 中的代码以及任何其他协程分开执行。但它一直在第一个 launch{} 内循环

    标签: kotlin kotlin-coroutines


    【解决方案1】:

    Log.e 是挂起函数吗?如果不是,那么您的第一个协程永远不会调用另一个挂起函数,也永远不会显式让步,因此它永远不会给其他协程在同一线程上运行的机会。

    对 runBlocking 的调用使用仅使用一个线程的默认调度程序,因此没有可用于运行第二个协程的线程。

    您可以通过在每次循环迭代后显式屈服来解决此问题:

    suspend fun printOne() {
        while (flag == false) {
            Log.e("log", "111111")
            yield() // <-- give other coroutines a turn
        }
    }
    

    如果您尝试使用不同的调度程序(如runBlocking(Dispatchers.IO))来解决问题,您可能会注意到另一个问题...

    flag 变量不是易失的。一个线程中运行的协程对变量所做的更改可能很长时间内不会被不同线程中的协程看到(如果有的话)。您可以通过将属性注释为 volatile 来解决此问题:

    @Volatile
    var flag = false
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-20
      • 1970-01-01
      • 2021-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      相关资源
      最近更新 更多