並行性とは?多くのことを同時にさばく
並行性は、たとえどの瞬間でも実際に実行しているのが 1 つだけでも、同時に進行中の多くのタスクを扱えるようプログラムを構成することです。
並行性は、多くのユーザーへの対応、複数ファイルのダウンロード、応答性を保ちながらのバックグラウンド処理など、複数の活動をさばくプログラムについての考え方です。タスクは時間的に重なりますが、必ずしも全く同じ瞬間に実行されるわけではありません。この区別、すなわち並行性と parallelism の違いが、多くの人をつまずかせます。
並行性が本当に意味すること
並行プログラムは独立して進行するタスクから構成されます。システムはそれらを交錯させ、タスク間で切り替えて各々を進めます。単一のコアでは一度に 1 つしか動きませんが、すべてが「進行中」であり、それでプログラムの応答性を保つには十分です。
並行性と parallelism
並行性は多くのことを同時にさばくこと(構造)についてです。parallelism は多くのことを同時に行うこと(実行)についてです。parallelism なしの並行性(タスクを切り替える 1 コア)はありえますし、parallelism は並行の作業を実行する 1 つの方法です。
並行性を表現する方法
- OS がコアにスケジュールする thread。
- I/O バウンドの作業のための、event loop 上の async/await。
- 協調的に制御を譲る coroutine。
- 分離されたプロセスや actor 間の message-passing。
難しい部分: 共有状態
並行タスクが可変データを共有すると、順序が重要になり、race condition や deadlock のようなバグが現れます。並行プログラミングの規律の多くは、共有状態を調整するか避けることに関わっています。
簡単な例
1000 の接続を並行してさばく web サーバーに 1000 のコアは必要ありません。接続を交錯させ、データが準備できたものから処理するため、すべてが進みます。
CI における並行性
CI は並行性を多用します。並列なテストシャード、並行 job、重なり合う I/O です。その速さには、flaky なテストとして現れるタイミングに敏感なバグが伴います。Latchkey は十分な並行 runner のキャパシティを提供し、本当に racy なテストを安定させる間、一時的な失敗を自動 retry します。
重要なポイント
- 並行性は、同時に進行中の多くのタスクを中心にプログラムを構成することです。
- parallelism とは異なります。並行性は構造、parallelism は同時実行です。
- 共有された可変状態こそ、race や deadlock のような並行性のバグが潜む場所です。