567 Views
November 29, 24
スライド概要
2024年11月29日に開催された「関西モバイルアプリ研究会A #6」で Swift Concurrency について話してきました。
今回のこのお話は、先日に「千歳ゆるい勉強会vol.4」で発表した「Swift Concurrency 要諦」をベースに、今回の持ち時間 5 分に合わせてカット・再編したものになります。千歳では間延びした感もあったので、今回はより概要を駆け足で掴みやすいように解説をスリムに抑えてみました。取り上げる話題も主要なキーワードだけにもしたので、よりピンポイントに要所をかいつまめるように仕上げてみてあります。
正統派趣味人プログラマー。プログラミングとは幼馴染です。
再編 Swift Concurrency 要諦 熊谷友宏 @es̲kumagai 2024/10/20 千歳ゆるい勉強会 vol.4 → 2024/11/29 関西モバイルアプリ研究会A #6
▶︎ ▶︎ ▶︎ ▶︎ 熊谷 友宏 Tomohiro Kumagai Swift 言語が好み 小さな勉強会を開催(2014年9月27日より) 株式会社ゆめみさんで 熊谷さんのやさしい Swift 勉強会 開催 & コードレビュー プログラミングの楽しさを伝えていきたい
Swift 5.5 に登場 → 6.0 で本格始動 Swift Concurrency ※ 今は Swift 6.0 が最新
▶︎ ▶︎ Swift Concurrency 並行処理を行うための仕組み Swift でも async / await が使えるようになった // 非同期関数を定義 func exec() async // 関数を非同期で実行 await exec()
否 本質 は どうやら それでは ないらしい。
Swift Concurrency 要諦
▶︎ ▶︎ ▶︎ Swift Concurrency とは 並行処理を安全に行うための仕組み 並行処理を Swift が把握して データ競合が起きる可能性を排除 async / await は その一環
▶︎ ▶︎ ▶︎ Swift Concurrency 本質 並行処理を安全に行う データ競合の発生を未然に阻止 競合状態の発生可能性を可視化 ※ 並行安全のコンパイラー支援が魅力
▶︎ ▶︎ Swift Concurrency データ競合とは 非同期処理で、予期しないデータになる現象 ひとつのメモリーを複数箇所で共有して、同時に参照、 そこに書込処理が伴うときに発生する ̶ ことがある ※ 再現性が低くなりがちで、デバッグを難しくする ※ これを未然に防ぐのが Swift Concurrency の存在意義
▶︎ ▶︎ Swift Concurrency 競合状態とは 非同期処理で、予期しないデータになる現象 ある一連の処理を実行中、別の処理が並行して走ったときに 意図した計算結果にならない ̶ ことがある ※ 再現性が低くなりがちで、デバッグを難しくする ※ これを可能な範囲で予防し、潜在箇所を視覚化するのが Swift Concurrency の存在意義
並行処理の時代 データ競合の回避は 人類の ⋯ ※ データ競合や競合状態は、マルチスレッドでは無視できない問題 夢
並行処理の時代 イミュータブルクラス ロック データ競合の回避は 人類の シリアルキュー ロックフリー などなど ※ データ競合や競合状態は、マルチスレッドでは無視できない問題 ⋯ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ メモリーを共有しない 夢
並行処理の時代 イミュータブルクラス ロック データ競合の回避は 人類の シリアルキュー ロックフリー などなど 夢 Swift Concurrency ※ データ競合や競合状態は、マルチスレッドでは無視できない問題 ⋯ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ メモリーを共有しない NEW
人類の夢 Swift Concurrency
▶︎ ▶︎ ▶︎ Swift Concurrency 導入された概念 タスク • 非同期処理の実行単位 • 実行スレッドはシステムが管理 隔離領域 • データの保護単位 • 領域を越えての扱いを制限 → データ競合を防ぐ 中断ポイント • 非同期処理の結果を待つ • スレッド自体のブロックはしない
▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ ▶︎ Swift Concurrency 導入されたキーワード(抜粋) async Task @Sendable await actor Actor Sendable @globalActor nonisolated GlobalActor @MainActor isolated sending #isolation
Swift Concurrency みんな知っている機能
▶︎ みんな知っている機能 1. async 付与した関数や変数が 非同期で実行されることを印付ける • 非同期での呼び出しを要求 • 引数や戻り値は、タスクを跨いで受け渡される func method(value: String) async -> Int var property: String { get async } async let result = await exec()
▶︎ みんな知っている機能 2. await 付与した関数や変数を非同期で実行することを印付ける • 引数や戻り値は、タスクを跨いで受け渡しする • 非同期実行している間は処理を中断して待つ let result = await method(value: "TEST") await print(property)
Swift Concurrency よく使われる機能
▶︎ よく使われる機能 1. Task ブロック内が 非同期で実行されることを印付ける • タスクを新規に立ち上げて、呼び出しを実施 • キャプチャーした値やタスクからの戻り値は、タスクを跨ぐ Task { } Task.detached { }
▶︎ よく使われる機能 2. actor インスタンスで隔離領域をつくることを印付ける型 • プロパティーをデータ競合から保護 • メソッドを競合状態から保護 • インスタンス単位で隔離領域を作り、メンバー同士は並行処理をしない • 外部からのメソッド呼出やプロパティー参照は 非同期扱い actor Operator { var state: Value func execution() }
▶︎ よく使われる機能 3. Sendable 並行安全であることを印付けるプロトコル • 隔離領域を越えて安全に受渡可能 • 並行安全な型だけが準拠している • コンパイラーが安全性を検証できなくても強制適用が可能 struct Value: Sendable { } struct Object: @unchecked Sendable { }
▶︎ よく使われる機能 4. nonisolated 非隔離であることを印付ける • 隔離領域による保護が行われない • 同期的に処理される • 通常の関数や変数は、暗黙的に nonisolated 扱いされる nonisolated func something() nonisolated(unsafe) var value: Value
▶︎ よく使われる機能 5. @MainActor メインアクター隔離であることを印付ける • いわゆるメインスレッドで処理される • プロパティー、関数、メソッド、型、タスクなどで指定可能 • 通常は非同期扱い、メインアクター隔離内では同期扱い @MainActor func something() @MainActor struct View { } @MainActor var value: Value Task { @MainActor in }
Swift Concurrency 覚えておきたい特色
▶︎ ▶︎ ▶︎ 覚えておきたい特色 中断ポイントと再入可能性 同じ隔離領域のタスクは同時実行されない(非隔離領域を除く) await では結果が得られるまで処理を中断 中断している間は、その隔離領域で別のタスクを実行可能 Task { @MainActor in Task { @MainActor in actionA() actionB() } actionX() actionY() }
▶︎ ▶︎ ▶︎ 覚えておきたい特色 中断ポイントと再入可能性 同じ隔離領域のタスクは同時実行されない(非隔離領域を除く) await では結果が得られるまで処理を中断 中断している間は、その隔離領域で別のタスクを実行可能 Task { @MainActor in actionA() await something() actionB() } Task { @MainActor in actionX() actionY() }
まとめ
▶︎ ▶︎ Swift Concurrency まとめ Swift Concurrency の本質 データ競合を起こさせないためにのみ存在する 思いのほか、追加機能はたくさん コードに印を付けて、データ競合の可能性を Swift が 見つけられるようにするのが Swift Concurrency の醍醐味
Enjoy! Swift Thank you 熊谷友宏 @es̲kumagai