この記事では、Swift の並行処理の仕組みを、舞台の俳優とその演技に使う小道具のイメージを用いて解説します。ここでは、以下のようなアナロジーを使います:
- actor: 舞台上で独立した役割を果たす俳優
- await: 俳優が自分のセリフ(処理)を終えるのを待ってから、次のシーンに進むタイミング
- Sendable: 俳優同士が台本に沿って安全に情報を交換できる仕組み
- public struct: 舞台上で俳優が使用する小道具、たとえば「封筒に入った手紙」。この手紙は一度作られると内容が変わらず、どのシーンでも同じ安全な情報を伝えます。
Swift の並行処理と舞台のイメージ
Swift は複数のタスクやスレッドが同時に動く並行処理をサポートしています。しかし、複数の作業が同時に同じデータにアクセスすると、予期しないエラー(データ競合やレースコンディション)が発生するリスクがあります。これを防ぐため、Swift ではいくつかの仕組みが用意されています。
actor: 舞台の俳優
-
独立した役割:
actor は、舞台上で各俳優が自分の役割(内部状態や処理)をしっかり果たすように、他と干渉せずに独立して動きます。 -
台本(メッセージパッシング):
俳優同士は台本に沿ってセリフをやり取りしながら演技します。同じように、actor は必要な情報をメッセージパッシングを通じて交換し、並行環境で安全に処理を行います。
await: セリフ終了を待つタイミング
-
待機の役割:
await は、俳優が自分のセリフ(非同期処理)を終えるのを待ってから次のシーンに進むように、処理の完了を待つためのキーワードです。 -
正しい進行:
これにより、actor の処理結果が確実に返ってくるまで次の命令に進まないので、全体の動作がスムーズかつ安全になります。
Sendable: 安全な情報交換の台本
-
安全性の保証:
Sendable プロトコルは、ある型の値が並行環境間で安全に共有・転送できることを保証します。 -
俳優の台本:
俳優同士が台本に従って必要な情報を正しくやり取りするように、Sendable に準拠している型は、どのシーンでも安全に情報が渡されることが保証されます。
public struct を封筒に入った手紙に例える
public な構造体(struct)は、モジュール外でも利用されるため、特に安全性が求められます。
ここで、public struct を 「封筒に入った手紙」 に例えてみましょう。
-
封筒に入った手紙:
一度印刷された手紙は内容が変わりません。同じ封筒に入った手紙は、どのシーン(タスクやスレッド)に持って行っても、同じ情報を伝えます。 -
不変性:
public struct が持つ値がイミュータブル(変更不可能)であれば、まさにこの封筒に入った手紙のように、安全に他の環境へ転送することができます。 -
Sendable の保証:
public な型は外部に公開されるため、Swift コンパイラは自動で Sendable と判断しません。開発者が明示的にSendable
に準拠させることで、まるでどのシーンに出ても安心して使える「信頼できる封筒に入った手紙」であることを保証するのです。
例: public struct の宣言
public struct MyPoint: Sendable {
public let x: Int
public let y: Int
public init(x: Int, y: Int) {
self.x = x
self.y = y
}
}
このように、public struct を Sendable に準拠させることで、どのシーン(並行環境)においても安全にその情報(手紙)が渡されることを保証します。
内部型と public 型の違い
-
内部型の場合:
internal や private な型は、モジュール内だけで使用されるため、すべてのプロパティがイミュータブルであれば、Swift は自動的に Sendable と推論することがあります。これは、舞台裏で俳優同士が安全に連携している状況に似ています。 -
public 型の場合:
public 型は、外部のモジュールや環境でも使われるため、より厳密な安全性が求められます。コンパイラは自動で Sendable と判断せず、明示的な準拠宣言が必要です。これは、スポットライトを浴びる舞台俳優が、どのシーンでも安全に演技できるように、事前に安全性を保証する必要があるのと同じです。
まとめ
-
actor と await:
- actor: 舞台の俳優のように、各 actor は独立した役割を持ち、自分の内部状態を安全に管理し、台本(メッセージパッシング)を通じて必要な情報をやり取りします。
- await: 俳優が自分のセリフを終えるのを待ってから次のシーンに進むように、await は非同期処理の完了を待つためのキーワードです。
-
Sendable と型の安全性:
-
内部型:
モジュール内であれば、自動的に Sendable と推論される場合があります。 -
public 型(actor や struct):
外部に公開されるため、明示的に Sendable に準拠させる必要があり、これは信頼できる「封筒に入った手紙」や、どのシーンでも安全に演技できる俳優として保証されることを意味します。
-
これらの仕組みを理解することで、Swift の並行処理における安全な情報交換がどのように実現されているかを、舞台の俳優や封筒に入った手紙のイメージで直感的に把握できます。これを活用して、堅牢で効率的な Swift コードを書いていきましょう!