プログラミング基礎概念

コルーチン こるーちん

非同期処理並行処理サスペンドasync/awaitスレッドジェネレーター
コルーチンについて教えて

簡単に言うとこんな感じ!

コルーチンは「途中で一時停止して、あとで再開できる関数」のことだよ!普通の関数は呼び出したら最後まで一気に走るけど、コルーチンは「ちょっと待ってて!」って止められて、また続きから動かせるんだ。料理しながら洗濯機を回すみたいな”ながら作業”をプログラムで実現できる仕組みってこと!


コルーチンとは

コルーチン(Coroutine)とは、実行を途中で一時停止(サスペンド)し、あとで再開できるプログラムの実行単位のことです。“Co-routine”という名前は「協調して動くルーチン(関数)」という意味を持ちます。通常の関数(サブルーチン)が「呼び出し→実行→返却」という一方通行なのに対して、コルーチンは呼び出し元と呼び出し先が互いに制御を譲り合いながら動くことができます。

ビジネスの現場では、Webアプリのデータ取得・ファイルの読み書き・APIの呼び出しなど、待ち時間が発生する処理を効率化する手段としてコルーチンが活用されています。KotlinPythonJavaScriptなど多くのモダンな言語に組み込まれており、システム開発の発注仕様を確認するときに「async/await(非同期処理)を使っています」と書かれていたら、その裏側にコルーチンの概念が使われていると思って間違いありません。

コルーチンの最大のメリットは、スレッド(独立した実行の流れ)を大量に作らなくても、並行処理を実現できる点です。スレッドはOSが管理するため生成コストが高いのですが、コルーチンはプログラム側で管理するため非常に軽量です。数万~数十万のコルーチンを同時に動かすことも現実的にできます。


コルーチンの仕組みと構造

コルーチンを理解するには「通常の関数との違い」を押さえるのが一番の近道です。

比較項目通常の関数(サブルーチン)コルーチン
実行の流れ呼び出し→一気に最後まで実行途中で一時停止・再開が可能
制御の主体呼び出し元が一方的に制御呼び出し元と呼び出し先が協調
状態の保持終了後は状態が消える停止中も状態(変数など)を保持
並行実行同時に複数動かすにはスレッドが必要1スレッド上で複数を切り替えられる
代表的な用途計算処理・変換処理など非同期I/O・アニメーション・ゲームなど

コルーチンの状態遷移

コルーチンは以下の3つの状態を行き来します。

  ┌─────────┐   呼び出し   ┌─────────┐
  │  待機中  │ ──────────► │  実行中  │
  │(Created) │             │(Running) │
  └─────────┘             └────┬────┘
       ▲                        │ サスペンド(一時停止)
       │ 再開                   ▼
  ┌─────────┐             ┌─────────┐
  │ 再開待ち │ ◄────────── │ 停止中  │
  │(Resumed) │             │(Suspended)│
  └─────────┘             └─────────┘

覚え方:「コルーチン=コラボするルーチン」

ラボするルーチン」と覚えましょう。関数同士が交互に制御を渡し合いながら協力して動くイメージです。コラボ(Co-)というプレフィックスが「協調」を表しているとイメージすると、通常の関数との違いが直感的につかめます。

主な言語での実装例

言語書き方のキーワード代表的な用途
Pythonasync def / await / yieldデータ取得・スクレイピング
JavaScript/TypeScriptasync / await / function*Webフロントエンド・Node.js
Kotlinsuspend / launch / asyncAndroidアプリ開発
Gogoroutine / channelサーバーサイド・マイクロサービス
C#async / await.NETアプリ・Unity

歴史と背景

  • 1958年 — コンピューターサイエンスの先駆者 メルビン・コンウェイ(Melvin Conway) がコルーチンの概念を提唱。アセンブリ言語のコンパイラ設計で活用したことが始まり
  • 1963年 — コンウェイが論文 “Design of a Separable Transition-Diagram Compiler” で正式に概念を発表
  • 1970年代〜1980年代 — COBOLやSimulaなどに影響を与えるも、主流にはならず。スレッドモデルが並行処理の主流に
  • 1990年代〜2000年代 — Pythonにジェネレーター(yield)が導入され、コルーチンの前身となる仕組みが普及し始める
  • 2012年 — C# 5.0で async/await が導入され、コルーチンベースの非同期処理がエンタープライズ開発に普及
  • 2015年 — JavaScript(ES2017)でも async/await が標準化に向けて動き出し、Webフロントエンド開発でも一般化
  • 2018年〜現在 — KotlinのCoroutines、Pythonのasyncioなどモダンなフレームワークがコルーチンをファーストクラスの機能として採用。スマホアプリ・サーバーサイドの両方で標準的な手法に

スレッドとの違い・非同期処理との関係

コルーチンと混同しやすい概念が「スレッド」と「非同期処理」です。それぞれの関係を整理します。

コルーチン・スレッド・非同期処理の関係 スレッド OSが管理する実行単位 生成コストが高い 本当の並列実行が可能 (マルチコア活用) 同期制御が複雑 (デッドロックに注意) 例: Javaのスレッド C++のstd::thread コルーチン プログラムが管理する 軽量な実行単位 協調的マルチタスク (自分で制御を渡す) 待ち時間を有効活用 (I/O待ちで切り替え) 例: Kotlin Coroutines Python asyncio 非同期処理(概念) 結果を待たずに 次の処理に進む考え方 スレッドでもコルーチンでも 実現できる コルーチンは非同期処理を 書きやすくする道具 例: コールバック関数 Promise / async/await 非同期処理はあくまで「概念」。スレッドとコルーチンはその実現手段

async/await との関係

async/await という書き方は、コルーチンを人間にとって読みやすい形で書くための構文です。裏側ではコルーチンのサスペンド・再開が行われています。

# Pythonの例:コルーチンを使った非同期処理
import asyncio

async def データ取得(url):
    print(f"{url} の取得を開始...")
    await asyncio.sleep(2)   # ← ここで一時停止(他の処理に制御を渡す)
    print(f"{url} の取得が完了!")
    return "データ"

async def メイン():
    # 2つのコルーチンを同時に実行(どちらかが待つ間に他方が動く)
    await asyncio.gather(
        データ取得("https://api.example.com/A"),
        データ取得("https://api.example.com/B"),
    )

asyncio.run(メイン())
# → 2秒待つのは1回だけ!(逐次実行なら4秒かかるところを2秒に短縮)

関連用語

  • 非同期処理 — 結果を待たずに次の処理へ進む実行モデル
  • スレッド — OSが管理するプログラムの独立した実行単位
  • ジェネレーターyieldで値を逐次生成するコルーチンの原型的な仕組み
  • イベントループ — コルーチンの切り替えを管理する中心的な仕組み
  • 並行処理 — 複数の処理を同時進行させる設計のアプローチ全般
  • 並列処理 — 複数のコアを使って文字通り同時に処理を実行すること
  • Promise — JavaScriptにおける非同期処理の結果を扱うオブジェクト
  • マルチタスク — 複数のタスクを切り替えながら実行する仕組みの総称