Swift Concurrency 要諦 #love_swift #関モバ #ゆるちとせ

5K Views

March 04, 25

スライド概要

2024年11月29日に開催された「集まれSwift好き!Swift愛好会 vol.92 @ DeNA」で Swift Concurrency について話してきました。

Swift Concurrency の本質に着目した話題になっています。この話題はこれまでにも「千歳ゆるい勉強会vol.4」と「関西モバイルアプリ研究会A #6」で発表していたのですけれど、今回向けに資料を整えていたら、今さらながら理解が足りないところに気がつきまして、そんな理解不足を訂正して誂え直したスライドになります。

なお、時間の都合で話さなかった部分があるので、それを含めた完全版も https://www.docswell.com/s/es_kumagai/KL18E7-2025-03-08-021753 に用意しました。

profile-image

正統派趣味人プログラマー。プログラミングとは幼馴染です。

Docswellを使いましょう

ダウンロード

関連スライド

各ページのテキスト
1.

訂正版 Swift Concurrency 要諦 熊谷友宏 @es̲kumagai 2024/10/20 千歳ゆるい勉強会 vol.4 2024/11/29 関西モバイルアプリ研究会A #6 2025/03/04 集まれSwift好き!Swift愛好会 vol.92 @ DeNA

2.

▶︎ ▶︎ ▶︎ ▶︎ 熊谷 友宏 Tomohiro Kumagai Swift 言語が好み 小さな勉強会を開催(2014年9月27日より) 株式会社ゆめみさんで 熊谷さんのやさしい Swift 勉強会 開催 & コードレビュー • いろんな人のレビューをしたい機運が高まり中 • 言語仕様を学ぶことの効果の高さを実感中 プログラミングの楽しさを伝えていきたい

3.

▶︎ ▶︎ ▶︎ 熊谷 友宏 Tomohiro Kumagai 技術同人誌の制作 らしい表現を目指そう、Swift イニシャライザー大全 • Swift プログラマーのための新千歳空港入門 同人誌即売会への出展 • 技術書典、おもしろ同人誌バザール、 コミックマーケット、コミティア(NEW) プログラミングの楽しさを伝えていきたい

4.

Swift 5.5 に登場 → 6.0 で本格始動 Swift Concurrency ※ 今は Swift 6.0 が最新

5.

▶︎ ▶︎ Swift Concurrency 並行処理を行うための仕組み(?) Swift でも async / await が使えるようになった(?) // 非同期関数を定義 func exec() async // 関数を非同期で実行 await exec()

6.

▶︎ ▶︎ Swift Concurrency 並行処理を行うための仕組み(?) Swift でも async / await が使えるようになった(?) 本質 は // 非同期関数を定義 func exec() async // 関数を非同期で実行 await exec() そこでは ないらしい。

7.

Swift Concurrency 要諦

8.

▶︎ ▶︎ Swift Concurrency とは 並行処理を安全に行うための仕組み async / await は その一環

9.

▶︎ ▶︎ ▶︎ Swift Concurrency 本質 並行処理を安全に行う データ競合 の発生を未然に阻止 競合状態 の発生可能性を可視化 ※ 並行安全のコンパイラー支援が魅力

10.

▶︎ ▶︎ Swift Concurrency データ競合 とは 非同期処理で 予期しないデータになる現象 ひとつのメモリーを複数箇所で同時に参照、 そこに書込処理が伴うときに発生する ことがある ※ Swift Concurrency によって、この発生が未然に阻止される

11.

▶︎ ▶︎ Swift Concurrency 競合状態 とは 非同期処理で 予期しないデータになる現象 ある一連の処理を実行中に別の処理が並行して走ったときに 意図した計算結果にならない ことがある ※ Swift Concurrency によって、この発生可能性が視覚化される

12.

並行処理の時代 ̶ データ競合の回避は 人類の夢 ⋯ ※ データ競合や競合状態は、マルチスレッドでは無視できない問題

13.

データ競合の回避は 人類の夢 メモリーを共有しない シリアルキュー イミュータブルクラス ロックフリー ロック ※ データ競合や競合状態は、マルチスレッドでは無視できない問題 ⋯ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ 並行処理の時代 ̶ などなど

14.

データ競合の回避は 人類の夢 メモリーを共有しない シリアルキュー イミュータブルクラス ロックフリー ロック Swift Concurrency などなど ※ データ競合や競合状態は、マルチスレッドでは無視できない問題 ⋯ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ 並行処理の時代 ̶ NEW

15.

人類の夢 Swift Concurrency

16.

▶︎ ▶︎ ▶︎ Swift Concurrency 導入された概念 タスク • 非同期処理の実行単位 • 実行スレッドはシステムで管理 中断ポイント • 非同期処理の結果を待つ • 実行スレッドをブロックせずに待つ 隔離領域 • データの保護単位 • 領域を越える値の扱いを制限 ※ Swift Concurrency は、この3つの概念を把握することが肝要

17.

▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ Swift Concurrency 導入されたキーワード async Task @Sendable await Sendable Actor actor @globalActor @MainActor GlobalActor nonisolated isolated sending #isolation などなど

18.

▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ Swift Concurrency 導入されたキーワード async Task @Sendable await Sendable Actor actor @globalActor @MainActor GlobalActor nonisolated isolated 頻繁に使う これらに着目 sending #isolation などなど

19.

Swift Concurrency キーワードまわりの要所

20.

▶︎ Swift Concurrency 1. async 非同期での実行を前提とすることを印付ける • 内部の処理で、非同期処理の実行や 自身の処理を中断可能 • カレントタスクで実行 される • 隔離領域の切り替えには関与しない (期待する隔離領域は別の方法で指定) func method(value: String) async -> Int var property: String { get async } async let result = await exec()

21.

▶︎ Swift Concurrency 2. await 非同期で実行することを印付ける • 式を非同期で実行し、その 処理完了まで中断 して待つ • カレントタスクで実行 する • 隔離領域を切り替えるかは呼出先に依存 let result = await method(value: "TEST") await print(property)

22.

▶︎ Swift Concurrency 3. Task ブロック内が 非同期で実行されることを印付ける • ブロック内の処理を 新規タスクで開始 し、ここでは 処理を中断しない • ブロックに渡す値や戻り値は タスクを越えて渡される • 隔離領域を引き継ぐかは、状況次第 // 子タスクを形成 // キャンセル状態・隔離領域・優先順位を継承 Task { … } // 独立したタスクを形成 Task.detached { … }

23.

▶︎ Swift Concurrency 4. Sendable 並行安全であることを印付けるプロトコル • 並行安全な型だけに適用できる • インスタンスは、自由に 隔離領域 や タスクを越えられる • 並行安全性を コンパイラーで保証するか、プログラマーが保証するかを選択可能 (スレッドセーフ) // 型の並行安全性はコンパイラーが保証してくれる struct Value: Sendable { … } // 型の並行安全性はプログラマーが保証しなければならない struct Object: @unchecked Sendable { … }

24.

▶︎ Swift Concurrency 5. actor インスタンス単位で隔離領域をつくる型 • インスタンス単位で 隔離領域 を形成 • 機能へのアクセスは 自身の隔離領域で実施させる • 複数箇所からの編集を伴う同時アクセスを阻止 actor Operator { var state: Value func execute() } let operator = Operator() Task { await operator.execute() }

25.

▶︎ Swift Concurrency 6. @MainActor メインアクター隔離であることを印付ける • メインスレッドによる保護を提供する隔離領域 で扱うことを示す • 処理の実行を メインスレッド に限定し、複数箇所からの同時アクセスを阻止 • プロパティー・関数・メソッド・型・タスク などに付与して使う @MainActor func something() @MainActor struct View { } @MainActor var value: Value Task { @MainActor in }

26.

Swift Concurrency 概念まわりの要所

27.

▶︎ ▶︎ ▶︎ ▶︎ Swift Concurrency タスクと隔離領域 タスク内の処理は 逐次処理(並行処理されない) 複数のタスクは 同時並行で処理 される ひとつの 隔離領域で、同時に処理できるのはひとつ だけ 隔離領域を使用中は、その処理が 中断 または 終了 するまで 次の処理は実施されない(呼出元は 中断して待つ)

28.

▶︎ ▶︎ ▶︎ Swift Concurrency 中断ポイントと再入可能性 async な機能は、await による 非同期実行(中断の可能性あり) ただし 同じ隔離領域での動作なら await なし の同期実行(即時実行) await では、結果が得られるまでタスクは処理を中断 中断している間は、その隔離領域 で 別のタスクを実行可能 Task { @MainActor in Task { @MainActor in actionA() await someActor.someAction() actionB() } ここで中断されたときに 別のタスクを実行開始 actionX() actionY() }

29.

まとめ

30.

▶︎ ▶︎ Swift Concurrency まとめ Swift Concurrency の本質 データ競合を起こさせないためにのみ存在する 思いのほか、追加機能はたくさん コードに印を付けて、データ競合の可能性を Swift が 見つけられるようにするのが Swift Concurrency の醍醐味

31.

Enjoy! Swift Thank you 熊谷友宏 @es̲kumagai