1. ホーム
  2. kotlin

[解決済み] Kotlinにおけるスレッドとコルーチンの違い

2023-02-03 05:39:48

質問

Kotlinの言語実装で、他の言語のコルーチンの実装と異なる点はありますか?

  • コルーチンは軽量スレッドのようなものというのはどういうことですか?
  • 何が違うのでしょうか?
  • kotlinのコルーチンは、実際に並列/並行で動作しているのでしょうか?
  • マルチコアシステムでも、コルーチンは常に1つしか実行されません(正しいですか)?

ここで、100000個のコルーチンを起動していますが、このコードの背後では何が起こっているのでしょうか?

for(i in 0..100000){
   async(CommonPool){
    //run long running operations
  }
}

どのように解決するのですか?

コルーチンを使うのはJVMだけなので、JVMのバックエンドの話をします。Kotlin NativeやKotlin JavaScriptもありますが、これらのKotlinのバックエンドは私の範囲外です。

では、Kotlinのコルーチンと他の言語のコルーチンを比較するところから始めましょう。基本的にコルーチンにはスタックレス型とスタックフル型の2種類があることを知っておくとよいでしょう。Kotlinはスタックレスコルーチンを実装しています。つまり、コルーチンはそれ自身のスタックを持たず、コルーチンができることを少し制限しています。詳しい説明は はこちら .

例です。

  • スタックレス。C#、Scala、Kotlin
  • スタックフル Quasar、Javaflow
<ブロッククオート

コルーチンは軽量スレッドのようなものだというのはどういうことですか?

Kotlinのコルーチンは独自のスタックを持たず、ネイティブスレッドにマッピングせず、プロセッサのコンテキストスイッチを必要としない、ということです。

何が違うのでしょうか?

スレッド - プリエンプティブにマルチタスクを行う。( 通常 ). コルーチン - 協力してマルチタスクを行う。

スレッド - OSによって管理される(通常)。 コルーチン - ユーザが管理する。

kotlinのコルーチンは実際に並列/同時進行しているのでしょうか?

各コルーチンを独立したスレッドで実行するか、すべてのコルーチンを1つのスレッドまたは固定スレッドプールで実行するかは、その方法次第です。

コルーチンの実行方法についてもっと詳しく はこちら .

<ブロッククオート

マルチコアシステムでも、常に1つのコルーチンしか動作していない(ということでいいのかな?)

いいえ、前の回答を参照してください。

<ブロッククオート

ここで100000コルーチンを開始していますが、このコードの背後では何が起こっているのでしょうか?

実は、それは場合によります。しかし、次のようなコードを書いたとします。

fun main(args: Array<String>) {
    for (i in 0..100000) {
        async(CommonPool) {
            delay(1000)
        }
    }
}

このコードは即座に実行されます。

からの結果を待つ必要があるため async の呼び出しの結果を待つ必要があるからです。

では、これを修正しましょう。

fun main(args: Array<String>) = runBlocking {
    for (i in 0..100000) {
        val job = async(CommonPool) {
            delay(1)
            println(i)
        }

        job.join()
    }
}

このプログラムを実行すると、kotlinは2 * 100000のインスタンスを作成して Continuation のインスタンスが生成され、数十MBのRAMを消費し、コンソールには1から100000までの数字が表示されます。

では、このコードをこのように書き換えてみましょう。

fun main(args: Array<String>) = runBlocking {

    val job = async(CommonPool) {
        for (i in 0..100000) {
            delay(1)
            println(i)
        }
    }

    job.join()
}

これでどうでしょう?ここで、100001個のインスタンスを作成し Continuation のインスタンスしか作成されないので、より良い結果が得られます。

作成された各ContinuationはCommonPool(ForkJoinPoolの静的インスタンスである)上でディスパッチされ、実行される。