diff --git a/language-guide/concurrency.md b/language-guide/concurrency.md
index 58406d3d..9204796b 100644
--- a/language-guide/concurrency.md
+++ b/language-guide/concurrency.md
@@ -1,15 +1,13 @@
# 並行処理\(Concurrency\)
-最終更新日: 2025/02/22
+最終更新日: 2025/05/31
原文: https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html
非同期操作を行う。
-Swift には、構造化された方法で非同期および並行コードを書くためのサポートが組み込まれています。非同期コード\(_asynchronous code_\)は、コードは一度にプログラムの 1 箇所のみで実行されますが、後で中断\(_suspend_\)および再開\(_resume_\)できます。こうすることで、ネットワーク上のデータの取得やファイルの解析などの長く時間のかかる操作の途中で、UI の更新などの短い時間で完了できる操作を行い、その後引き続き操作を続けることができます。並列コード\(_parallel code_\)とは、複数のコードを同時に実行することを意味します。例えば、4 コアプロセッサを搭載したコンピュータは、各コアがタスクを 1 つ実行し、4 つのコードを同時に実行できます。並列および非同期コードを使用するプログラムは、一度に複数の操作を実行します。そして、外部システムからの結果を待つ操作を中断します。
+Swift には、構造化された方法で非同期および並行コードを書くためのサポートが組み込まれています。非同期コード\(_asynchronous code_\)は、コードは一度にプログラムの 1 箇所のみで実行されますが、後で中断\(_suspend_\)および再開\(_resume_\)できます。こうすることで、ネットワーク上のデータの取得やファイルの解析などの長く時間のかかる操作の途中で、UI の更新などの短い時間で完了できる操作を行い、その後引き続き操作を続けることができます。並列コード\(_parallel code_\)とは、複数のコードを同時に実行することを意味します。例えば、4 コアプロセッサを搭載したコンピュータは、各コアがタスクを 1 つ実行し、4 つのコードを同時に実行できます。並列および非同期コードを使用するプログラムは、一度に複数の操作を実行します。そして、外部システムからの結果を待つ操作を中断します。この章の残りの部分では、非同期コードと並列コードのこのよくある組み合わせを参照するために並行\(_concurrency_\) という用語を使用します。
-並列または非同期コードを使って様々なタスクを追加でスケジューリングできる柔軟性は、逆に複雑さが増すコストも伴います。Swift を使用すると、コンパイル時のチェックでコードの意図を表現できます。例えば、アクター\(_actor_\)を使用してその可変状態\(_mutable state_\)に安全にアクセスできます。ただし、元々処理速度の遅いコードやバグを含んだコードに並行処理を追加しても、処理速度が速くなったりコードが正しくなる、というようなことは保証されません。実際、並行処理を追加すると、コードのデバッグが余計に難しくなる可能性さえあります。ただし、並行に処理をする必要があるコードに Swift の言語レベルのサポートを使用することで、コンパイル時に問題をキャッチすることができます。
-
-この章の残りの部分では、非同期コードと並列コードのこの一般的な組み合わせを参照するために並行\(_concurrency_\) という用語を使用します。
+並列または非同期コードを使って様々なタスクを追加でスケジューリングできる柔軟性は、逆に複雑さが増すコストも伴います。並行コードを書く際、どのコードが同時に実行されるかを事前に知ることはできず、また、コードが実行される順序も常に把握できるとは限りません。並行コードにおけるよくある問題は、複数のコード片が何らかの共有された可変状態にアクセスしようとするときに発生します。これはデータ競合\(_data race_\)として知られています。言語レベルの並行処理サポートを使用すると、Swift はデータ競合を検出し防止します。そして、ほとんどのデータ競合はコンパイルエラーを生成します。一部のデータ競合は、コードが実行されるまで検出できず、コードの実行を終了させます。この章で説明するように、データ競合から保護するためにアクターと隔離を使用します。
> NOTE
> 過去に並行コードを書いたことがある場合は、スレッドの操作に慣れているかもしれません。Swiftの 並行モデルはスレッドの上に構築されていますが、直接スレッドとやり取りすることはありません。Swift の非同期関数は、実行中のスレッドを放棄することができ、最初の関数がブロックされている間、そのスレッド上で別の非同期関数を実行できます。非同期関数が再開するとき、その関数がどのスレッドで実行されるかについて、Swiftは何も保証しません。
@@ -26,7 +24,7 @@ listPhotos(inGallery: "夏休み") { photoNames in
}
```
-このような単純なケースでも、コードには一連の完了ハンドラを記述する必要があるため、ネストしてクロージャを書くことになります。このスタイルでは、より複雑な深いネストを持つコードはすぐに扱いにくくなってしまいます。
+このような単純なケースでも、コードには一連の完了ハンドラを書く必要があるため、ネストしてクロージャを書くことになります。このスタイルでは、より複雑な深いネストを持つコードはすぐに扱いにくくなってしまいます。
## 非同期関数の定義と呼び出し\(Defining and Calling Asynchronous Functions\)
@@ -43,8 +41,8 @@ func listPhotos(inGallery name: String) async -> [String] {
非同期かつエラーをスローする関数またはメソッドの場合は、`throws` の前に `async` を書きます。
-非同期メソッドを呼び出すと、そのメソッドが戻るまで実行が中断されます。中断する可能性のある_中断ポイント_\(_suspension point_\)を示すために、メソッド呼び出しの前に `await` を書きます。これは、スロー関数を呼び出すときにエラーが発生した場合にプログラムの流れを変更する可能性を示すために `try` を書くのと同様です。非同期メソッド内では、別の非同期メソッドを呼び出す場合にのみ、実行フローが中断されます。中断は決して暗黙的に処理を割り込むものではありません。つまり、全ての中断する可能性があるポイントには `await` をマークします。
-コードに中断する可能性のあるポイントをすべてマークすることで、同時実行されるコードを読みやすくし、理解しやすくできます。
+非同期メソッドを呼び出すと、そのメソッドが戻るまで実行が中断されます。中断する可能性のある_中断ポイント_\(_suspension point_\)を示すために、メソッド呼び出しの前に `await` を書きます。これは、スロー関数を呼び出すときにエラーが発生した場合にプログラムの流れを変更する可能性を示すために `try` を書くのと同様です。非同期メソッド内では、別の非同期メソッドを呼び出す場合にのみ、実行フローが中断される可能性があります。中断は決して暗黙的に処理を割り込むものではありません。つまり、全ての中断する可能性があるポイントには `await` をマークします。
+コードに中断する可能性のあるポイントを全てマークすることで、同時実行されるコードを読みやすくし、理解しやすくできます。
例えば、下記のコードは、ギャラリ内の全ての写真名を取得し、最初の写真を表示します:
@@ -68,25 +66,11 @@ show(photo)
5. 次の `await` は、`downloadPhoto(named:)` 関数の呼び出し時に示されています。このコードは、その関数が戻り値を返すまで再び実行を一時中断し、他の並行処理を実行する機会を与えます
6. `downloadPhoto(named:)` が戻り値を返し、その戻り値が `photo` に割り当てられ、`show(_:)` を呼び出すときに引数として渡されています
-`await` でマークされた、コード内で処理が中断する可能性のあるポイントは、非同期関数またはメソッドが戻るのを待っている間に、現在のコードが処理を一時中断することを示しています。内部では、Swift は、現在のスレッド上のコードの実行を中断し、代わりにそのスレッド上の他のコードを実行するため、これはスレッドを譲る\(_yielding the thread_\)と呼ばれます。`await` 時にコードを中断できるようにする必要があるため、プログラム内の特定の場所だけが非同期関数またはメソッドを呼び出すことができます:
+`await` がマークされた、コード内で処理が中断する可能性のあるポイントは、非同期関数またはメソッドが戻るのを待っている間に、現在のコードが処理を一時中断することを示しています。内部では、Swift は、現在のスレッド上のコードの実行を中断し、代わりにそのスレッド上の他のコードを実行するため、これはスレッドを譲る\(_yielding the thread_\)と呼ばれます。`await` 時にコードを中断できるようにする必要があるため、プログラム内の特定の場所だけが非同期関数またはメソッドを呼び出すことができます:
* 非同期の関数、メソッド、プロパティの本文
-* `@main` でマークされている構造体、クラス、または列挙型の `static main()` メソッド内
-* 下記の[Unstructured Concurrency\(独立した並行処理\)](concurrency.md#unstructured-concurrency)で示す独立した子タスク\(_child task_\)のコード
-
-あなたは[`Task.yield()`]( https://developer.apple.com/documentation/swift/task/3814840-yield)を呼び出すことで、明示的に中断する可能性のあるポイントを挿入できます。
-
-```swift
-func generateSlideshow(forGallery gallery: String) async {
- let photos = await listPhotos(inGallery: gallery)
- for photo in photos {
- // ...この画像のための数秒の動画をレンダリングする...
- await Task.yield()
- }
-}
-```
-
-ビデオをレンダリングするコードが同期的であると仮定した場合、中断ポイントは含まれていません。ビデオをレンダリングする作業にも時間がかかる可能性があります。しかし、明示的な中断ポイントを追加するために `Task.yield()` を定期的に呼び出すことができます。このように長時間実行するコードを構造化することで Swift はこのタスクの進捗と、プログラム内の他のタスクの進捗のバランスをとることができます。
+* `@main` がマークされている構造体、クラス、または列挙型の `static main()` メソッド内
+* 下記の[Unstructured Concurrency\(非構造化並行処理\)](concurrency.md#unstructured-concurrency)で示す非構造化子タスク\(_child task_\)のコード
[`Task.sleep(for:tolerance:clock:)`](https://developer.apple.com/documentation/swift/task/sleep(for:tolerance:clock:))メソッドは並行処理がどのように機能するかを学ぶためにシンプルなコードを書くのに便利です。このメソッドは、少なくとも指定した時間だけ現在のタスクを中断します。以下は `listPhotos(inGallery:)` 関数で、`sleep(for:tolerance:clock:)` を使ってネットワーク操作の待ち時間をシミュレートしています:
@@ -229,7 +213,7 @@ let photos = await withTaskGroup(of: Data.self) { group in
}
```
-前の例と同じように、この例でも写真ごとに子タスクを作成してダウンロードしています。前の例とは異なり、`for-await-in` ループは次の子タスクの終了を待ち、そのタスクの結果を結果の配列に追加して、すべての子タスクが終了するまで待ち続けます。最後に、タスクグループはダウンロードした写真の配列を全体の結果として返します。
+前の例と同じように、この例でも写真ごとに子タスクを作成してダウンロードしています。前の例とは異なり、`for-await-in` ループは次の子タスクの終了を待ち、そのタスクの結果を結果の配列に追加して、全ての子タスクが終了するまで待ち続けます。最後に、タスクグループはダウンロードした写真の配列を全体の結果として返します。
### タスクキャンセル\(Task Cancellation\)
@@ -239,15 +223,14 @@ Swift の並行処理では、協調キャンセルモデルを使用します
- `nil` または空のコレクションを返す
- 部分的に完了した作業を返す
-写真が大きかったり、ネットワークが遅かったりすると、写真のダウンロードに時間がかかることがあります。すべてのタスクが完了するのを待たずに、ユーザーがこの作業を停止できるようにするには、タスクがキャンセルをチェックし、キャンセルされたら実行を停止する必要があります。タスクがこれを行うには、[`Task.checkCancellation()` 型メソッド](https://developer.apple.com/documentation/swift/task/3814826-checkcancellation)を呼び出す方法と、[`Task.isCancelled` 型プロパティ](https://developer.apple.com/documentation/swift/task/iscancelled-swift.type.property)を読み取る方法の 2 つがあります。`checkCancellation()` を呼び出すと、タスクがキャンセルされていた場合にエラーがスローされます。スローされたタスクは、エラーをタスクの外に伝播し、タスクのすべての作業を停止することができます。これは実装が簡単で理解しやすいという利点があります。より柔軟にするには、`isCancelled` プロパティを使用します。このプロパティを使用すると、ネットワーク接続を閉じたり、一時ファイルを削除するなど、タスクの停止の一部としてクリーンアップ作業を実行できます。
+写真が大きかったり、ネットワークが遅かったりすると、写真のダウンロードに時間がかかることがあります。全てのタスクが完了するのを待たずに、ユーザーがこの作業を停止できるようにするには、タスクがキャンセルをチェックし、キャンセルされたら実行を停止する必要があります。タスクがこれを行うには、[`Task.checkCancellation()` 型メソッド](https://developer.apple.com/documentation/swift/task/3814826-checkcancellation)を呼び出す方法と、[`Task.isCancelled` 型プロパティ](https://developer.apple.com/documentation/swift/task/iscancelled-swift.type.property)を読み取る方法の 2 つがあります。`checkCancellation()` を呼び出すと、タスクがキャンセルされていた場合にエラーがスローされます。スローされたタスクは、エラーをタスクの外に伝播し、タスクの全ての作業を停止することができます。これは実装が簡単で理解しやすいという利点があります。より柔軟にするには、`isCancelled` プロパティを使用します。このプロパティを使用すると、ネットワーク接続を閉じたり、一時ファイルを削除するなど、タスクの停止の一部としてクリーンアップ作業を実行できます。
```swift
-let photos = await withTaskGroup(of: Optional.self) { group in
+let photos = await withTaskGroup { group in
let photoNames = await listPhotos(inGallery: "夏休み")
for name in photoNames {
let added = group.addTaskUnlessCancelled {
- guard !Task.isCancelled else { return nil }
- return await downloadPhoto(named: name)
+ Task.isCancelled ? nil : await downloadPhoto(named: name)
}
guard added else { break }
}
@@ -284,9 +267,11 @@ task.cancel() // Prints "キャンセルされた!"
キャンセルハンドラーを使用する場合、タスクのキャンセルはまだ協調的です。つまり、タスクを完了まで実行するか、途中でキャンセルをチェックして早期に停止する必要があります。キャンセルハンドラーが開始してもタスクはまだ実行中なので、タスクとキャンセルハンドラーの間で状態を共有することは避けてください。
-### 独立した並行処理\(Unstructured Concurrency\)
+### 非構造化並行処理\(Unstructured Concurrency\)
-前のセクションで説明されている構造化された並行処理のアプローチに加えて、Swift は独立した並行処理\(_unstructured concurrency_\)もサポートしています。タスクグループの一部のタスクとは異なり、独立したタスク\(_unstructured task_\)には親タスクがありません。どんな方法で使われたとしても、独立したタスクを完全に柔軟に管理することができます。しかし、それらの正しい動作を保証することは完全に開発者の責任です。現在のアクター\(_actor_\)上で実行される独立したタスクを作成するには、[Task.init\(priority:operation:\)](https://developer.apple.com/documentation/swift/task/3856790-init) 関数を呼びます。現在のアクター上で実行されないタスク\(切り離されたタスク\(_detached task_\)\)を作成するには、[Task.detached\(priority:operation:\)](https://developer.apple.com/documentation/swift/task/3856786-detached) 関数を呼び出します。これらの関数は両方ともタスクハンドル\(_task handle_\)を返し、例えば、その結果を待つかキャンセルすることができます。
+前のセクションで説明されている構造化された並行処理のアプローチに加えて、Swift は非構造化並行処理\(_unstructured concurrency_\)もサポートしています。タスクグループの一部のタスクとは異なり、非構造化タスク\(_unstructured task_\)には親タスクがありません。どんな方法で使われたとしても、非構造化タスクを完全に柔軟に管理することができます。しかし、それらの正しい動作を保証することは完全に開発者の責任です。
+
+周囲のコードと同様に実行される非構造化タスクを作成するには、[Task.init\(priority:operation:\)](https://developer.apple.com/documentation/swift/task/3856790-init) イニシャライザを呼びます。デフォルトで、現在のタスクと同じアクター隔離、優先度、およびタスクローカル状態で実行されます。周囲のコードからより独立した非構造化タスク(より具体的には切り離されたタスク\(_detached task_\)として知られるもの)を作成するには、[Task.detached\(priority:operation:\)](https://developer.apple.com/documentation/swift/task/3856786-detached) 関数を呼び出します。新しいタスクは、デフォルトでどのアクターにも隔離されずに実行され、現在のタスクの優先度やタスクローカル状態を継承しません。これらの操作はいずれも操作可能なタスクを返します。例えば、その結果を待機したり、キャンセルしたりできます。
```swift
let newPhoto = // ... ある写真データ ...
@@ -298,9 +283,94 @@ let result = await handle.value
切り離されたタスクの管理の詳細については、[Task](https://developer.apple.com/documentation/swift/task)を参照ください。
+## 隔離
+
+前のセクションでは、並行処理を分割するアプローチについて説明しました。その処理には、アプリの UI などの共有データの変更が含まれる場合があります。コードの異なる部分が同じデータを同時に変更できる場合、データ競合が発生するリスクがあります。Swift はコード内のデータ競合から保護します。データを読み取ったり変更したりするたびに、Swift は他のコードが同時にそれを変更していないことを保証します。この保証はデータ隔離\(_data isolation_\)と呼ばれます。データを隔離するには、主に 3 つの方法があります。
+
+1. 不変データは常に隔離されている。定数は変更できないため、読み取りと同時に他のコードが定数を変更するリスクはない
+2. 現在のタスクのみから参照されるデータは常に隔離されている。ローカル変数は、タスク外のコードがそのメモリへの参照を持たないため、安全に読み書きできる。したがって、他のコードがそのデータを変更することはできない。さらに、変数をクロージャでキャプチャする場合、Swift はそのクロージャが同時に使用されないことを保証する
+3. アクターによって保護されているデータは、そのデータにアクセスするコードもアクターに隔離されている場合に隔離される。現在の関数がアクターに隔離されている場合、そのアクターによって保護されているデータの読み書きは安全。なぜなら、同じアクターに隔離されている他のコードは、実行前に順番を待つ必要があるからだ
+
+## メインアクター\(The Main Actor\)
+
+アクターとは、コードに可変データへのアクセスを順番に行わせることで、そのデータへのアクセスを保護するオブジェクトです。多くのプログラムにおいて最も重要なアクターは、メインアクター\(_Main Actor_\)です。アプリでは、メインアクターは UI を表示するために使用される全てのデータを保護します。メインアクターは、UI のレンダリング、UI イベントの処理、そしてあなたが書いた UI のクエリや更新が必要なコードを順番に実行します。
+
+並行処理を使い始める前は、全てのコードがメインアクター上で実行されます。長時間実行される、またはリソースを大量に消費するコードを見つけた場合、安全かつ正しい方法でこの作業をメインアクターから移動させることができます。
+
+> 注: メインアクターはメインスレッドと密接に関連していますが、同じものではありません。メインアクターはプライベートな可変状態を持ち、メインスレッドはその状態へのアクセスを直列化します。メインアクター上でコードを実行すると、Swift はそのコードをメインスレッドで実行します。この関連性のため、これら 2 つの用語が同じ意味で使用されるのを見ることがあるかもしれません。あなたのコードはメインアクターとやり取りします。メインスレッドはより低レベルの実装詳細です。
+
+メインアクター上で作業を実行するにはいくつかの方法があります。関数が常にメインアクター上で実行されるようにするには、`@MainActor` 属性をマークします。
+
+```swift
+@MainActor
+func show(_: Data) {
+ // ... 写真を表示するためのUIコード ...
+}
+```
+
+上記のコードでは、`show(_:)` 関数にある `@MainActor` 属性は、この関数がメインアクター上でのみ実行されることを要求します。メインアクター上で実行されている他のコード内では、`show(_:)` を同期関数として呼び出すことができます。しかし、メインアクター上で実行されていないコードから `show(_:)` を呼び出すには、メインアクターへの切り替えが潜在的な中断ポイントになるため、`await` をマークして非同期関数として呼び出す必要があります。例えば、
+
+```swift
+func downloadAndShowPhoto(named name: String) async {
+ let photo = await downloadPhoto(named: name)
+ await show(photo)
+}
+```
+
+上記のコードでは、`downloadPhoto(named:)` 関数と `show(_:)` 関数の両方とも、呼び出すと中断する可能性があります。このコードはまた、よくあるパターンも示しています。つまり、長時間実行され CPU 負荷の高い作業をバックグラウンドで実行し、その後 UI を更新するためにメインアクターに切り替えるというパターンです。`downloadAndShowPhoto(named:)` 関数はメインアクター上にないため、`downloadPhoto(named:)` 内の作業もメインアクター上では実行されません。`show(_:)` 内の UI を更新するための作業のみがメインアクター上で実行されます。なぜなら、その関数は `@MainActor` 属性がマークされているからです。
+
+クロージャがメインアクター上で実行されるようにするには、クロージャの先頭、キャプチャリストの前、かつ `in` の前に `@MainActor` を書きます。
+
+```swift
+let photo = await downloadPhoto(named: "Trees at Sunrise")
+Task { @MainActor in
+ show(photo)
+}
+```
+
+上記のコードは、前のコードリストの `downloadAndShowPhoto(named:)` に似ていますが、この例のコードは UI の更新を待機しません。また、構造体、クラス、または列挙型に `@MainActor` を書くことで、その全てのメソッドとプロパティへの全てのアクセスがメインアクター上で実行されるようにできます。
+
+```swift
+@MainActor
+struct PhotoGallery {
+ var photoNames: [String]
+ func drawUI() { /* ... その他のUIコード ... */ }
+}
+```
+
+上記のコードの `PhotoGallery` 構造体は、`photoNames` プロパティの名前を使用して表示する写真を決定し、写真を画面に描画します。`photoNames` は UI に影響を与えるため、それを変更するコードは、そのアクセスを直列化するためにメインアクター上で実行される必要があります。
+
+フレームワーク上に構築する場合、そのフレームワークのプロトコルと基底クラスは通常、すでに `@MainActor` がマークされているため、その場合は通常、独自の型に `@MainActor` を書きません。以下に簡単な例を示します。
+
+```swift
+@MainActor
+protocol View { /* ... */ }
+
+// 暗黙的に@MainActor
+struct PhotoGalleryView: View { /* ... */ }
+```
+
+上記のコードでは、SwiftUI のようなフレームワークが `View` プロトコルを定義しています。プロトコル宣言に `@MainActor` を書くことで、プロトコルに準拠する `PhotoGalleryView` のような型も暗黙的に `@MainActor` がマークされます。`View` が基底クラスで `PhotoGalleryView` がサブクラスであった場合も同様の動作になり、サブクラスは暗黙的に `@MainActor` がマークされます。
+
+上記の例では、`PhotoGallery` は構造体全体をメインアクターで保護します。よりきめ細かく制御するために、メインスレッドでアクセスまたは実行する必要があるプロパティまたはメソッドにのみ `@MainActor` を書けます。
+
+```swift
+struct PhotoGallery {
+ @MainActor var photoNames: [String]
+ var hasCachedPhotos = false
+
+ @MainActor func drawUI() { /* ... UIコード ... */ }
+ func cachePhotos() { /* ... ネットワークコード ... */ }
+}
+```
+
+上記の `PhotoGallery` のバージョンでは、`drawUI()` メソッドはギャラリーの写真を画面に描画するため、メインアクターに隔離する必要があります。`photoNames` プロパティは UI を直接作成しませんが、`drawUI()` 関数が UI を描画するために使用する状態を格納するため、このプロパティもメインアクター上でのみアクセスされる必要があります。対照的に、`hasCachedPhotos` プロパティへの変更は UI と対話せず、`cachePhotos()` メソッドはメインアクターでの実行を必要とする状態にアクセスしません。そのため、これらは `@MainActor` がマークされていません。
+
+前の例と同様に、UI を構築するためにフレームワークを使用している場合、そのフレームワークのプロパティラッパは、おそらくすでに UI の状態プロパティを `@MainActor` でマークしています。プロパティラッパを定義する際、その `wrappedValue` プロパティが `@MainActor` がマークされている場合、そのプロパティラッパを適用する全てのプロパティも暗黙的に `@MainActor` がマークされます。
+
## アクター\(Actors\)
-タスクは、プログラムを隔離された並行処理の断片に分割するために使用できます。タスクは互いに隔離されているので並行に実行しても安全ですが、タスク間で何らかの情報を共有したい場合もあります。アクター\(_actors_\)を使用すると、並行処理をするコード間で安全に情報を共有することができます。
+Swift にはメインアクターが用意されており、また独自のアクターを定義することもできます。アクターは並行コード間で情報を安全に共有することを可能にします。
クラスのようにアクターは参照型なので、[Classes Are Reference Types\(クラスは参照型\)](../language-guide/structures-and-classes.md#classes-are-reference-types)の中の値型と参照型の比較はアクターにも当てはまります。しかし、クラスとは異なり、アクターの可変状態\(_mutable state_\)にアクセスできるのは一度に 1 つのタスクだけです。これにより、複数のタスクが、同じアクターのインスタンスとやり取りする必要があるコードでも、安全にアクセスできるようになります。例えば、下記は気温を記録するアクターです:
@@ -357,13 +427,13 @@ extension TemperatureLogger {
print(logger.max) // エラー
```
-アクターのプロパティはそのアクターの独立したローカル状態の一部のため、`await` を書かないと `logger.max` へのアクセスは失敗します。このプロパティにアクセスするコードは、アクタの一部として実行する必要があり、これは非同期操作であり、`await` を記述する必要があります。Swift は、実行されているコードのみがアクターに隔離されたローカルの状態にアクセスできることを保証します。この保証はアクター隔離\(_actor isolation_\)と呼ばれています。
+アクターのプロパティはそのアクターの独立したローカル状態の一部のため、`await` を書かないと `logger.max` へのアクセスは失敗します。このプロパティにアクセスするコードは、アクタの一部として実行する必要があり、これは非同期操作であり、`await` をマークする必要があります。Swift は、実行されているコードのみがアクターに隔離されたローカルの状態にアクセスできることを保証します。この保証はアクター隔離\(_actor isolation_\)と呼ばれています。
Swift の並行処理モデルの以下の側面は、共有された可変状態について推論しやすくするために一緒に機能します:
-- 中断する可能性のあるポイントの間のコードは、他の並行処理コードから中断される可能性はなく、順次実行されます
-- アクターのローカル状態と相互作用するコードは、そのアクター上でのみ実行されます
-- アクターは一度に 1 つのコードだけを実行します
+- 中断する可能性のあるポイントの間のコードは、他の並行処理コードから中断される可能性はなく、順次実行される。しかし、複数の並行コードは同時に実行される場合があるため、他のコードが同時に実行されている可能性がある
+- アクターのローカル状態と相互作用するコードは、そのアクター上でのみ実行される
+- アクターは一度に 1 つのコードだけを実行する
このような保証があるため、アクターの内部にあるコードは `await` を含まず、プログラム内の他の場所で一時的に不正な状態になるリスクなしに更新できます。例えば、以下のコードは測定された温度を華氏から摂氏に変換します:
@@ -379,7 +449,13 @@ extension TemperatureLogger {
上のコードでは、測定値の配列を一度に 1 つずつ変換しています。map 操作の進行中、いくつかの温度は華氏で、他の温度は摂氏です。しかし、どのコードにも `await` が含まれていないため、このメソッドには潜在的な中断ポイントがありません。このメソッドが変更する状態はアクターに属し、そのアクター上ではないコードが読んだり変更することから保護されています。つまり、単位変換の進行中に、他のコードが部分的に変換された温度のリストを読む方法がないということです。
-潜在的な中断ポイントをなくすことで一時的な不正状態から保護されているアクター内にコードを書くことに加えて、そのコードを同期メソッドに移すことができます。上記の `convertFahrenheitToCelsius()` メソッドは同期メソッドなので、潜在的な中断ポイントを含まないことが保証されています。この関数は、一時的にデータモデルの一貫性を失わせるコードをカプセル化し、データの一貫性を取り戻す前に他のコードが実行できないようにして作業を完了させることを、コードを読んだ人が簡単に認識できるようにします。将来、この関数に並行コードを追加して、潜在的な中断ポイントを導入しようとすると、バグを導入する代わりにコンパイルエラーが発生します。
+潜在的な中断ポイントをなくすことで一時的な不正状態から保護されているアクター内にコードを書くことに加えて、そのコードを同期メソッドに移すことができます。上記の `convertFahrenheitToCelsius()` メソッドは同期メソッドなので、潜在的な中断ポイントを含まないことが保証されています。この関数は、一時的にデータモデルの一貫性を失わせるコードをカプセル化し、データの一貫性を取り戻す前に他のコードが実行できないようにして作業を完了させることを、コードを読んだ人が簡単に認識できるようにします。その期間中、Swift がこのコードからプログラムの別の部分のコードを実行するために切り替えないことが重要です。将来、この関数に並行コードを追加して、潜在的な中断ポイントを導入しようとすると、バグを導入する代わりにコンパイルエラーが発生します。
+
+## グローバルアクター\(Global Actors\)
+
+メインアクターは、[MainActor](https://developer.apple.com/documentation/swift/mainactor) 型のグローバルなシングルトンインスタンスです。通常、アクターは複数のインスタンスを持つことができ、各インスタンスは独立した隔離を提供します。そのため、アクターに隔離されたデータはすべて、そのアクターのインスタンスプロパティとして宣言します。しかし、`MainActor` はシングルトンであるため(この型のインスタンスは常に 1 つしか存在しません)、型のみでアクターを識別するには十分であり、属性を使用するだけでメインアクター隔離をマークできます。このアプローチにより、自身にとって最適な方法でコードを構成するための、より大きな柔軟性が得られます。
+
+[globalActor](../language-reference/attributes.md#globalactor)で説明されているように、`@globalActor` 属性を使用して、独自のシングルトンのグローバルアクターを定義できます。
## `Sendable` 型\(Sendable Types\)
diff --git a/language-reference/attributes.md b/language-reference/attributes.md
index 4ceb9e0c..266aac5f 100644
--- a/language-reference/attributes.md
+++ b/language-reference/attributes.md
@@ -1,6 +1,6 @@
# 属性\(Attributes\)
-最終更新日: 2025/3/29
+最終更新日: 2025/5/31
原文: https://docs.swift.org/swift-book/ReferenceManual/Attributes.html
宣言と型に情報を追加する。
@@ -379,6 +379,14 @@ frozen 列挙型の switch 文は、[Switching Over Future Enumeration Cases\(
この属性を適用して、独自の GameplayKit コンポーネントプロパティを SpriteKit エディタ UI に公開します。この属性を適用すると、`objc` 属性も暗黙的に追加されます。
+### globalActor
+
+この属性はアクター、構造体、列挙型、または `final` クラスに適用します。その型は、アクターの共有インスタンスを提供する `shared` という名前の静的プロパティを定義する必要があります。
+
+グローバルアクターは、アクター隔離の概念を、コード内の複数の異なる場所(複数の型、ファイル、モジュールなど)に分散した状態で汎用化し、並行コードからグローバル変数に安全にアクセスできるようにします。グローバルアクターが `shared` プロパティの値として提供するアクターは、このすべての状態へのアクセスを直列化します。また、すべて同じスレッドで実行する必要があるコードのように、並行コードにおける制約をモデル化するためにグローバルアクターを使用することもできます。
+
+グローバルアクターは暗黙的に [`GlobalActor`](https://developer.apple.com/documentation/swift/globalactor) プロトコルに準拠します。メインアクターは、[メインアクター\(The Main Actor\)](../language-guide/concurrency.md#メインアクターthe-main-actor)で説明されているように、標準ライブラリによって提供されるグローバルアクターです。ほとんどのコードは、新しいグローバルアクターを定義する代わりにメインアクターを使用できます。
+
### inlinable
この属性を関数、メソッド、計算プロパティ、サブスクリプト、convenience イニシャライザ、またはデイニシャライザ宣言に適用すると、モジュールのパブリックインターフェイスの一部としてその宣言の実装を公開します。コンパイラは、inlinable シンボルへの呼び出しを、呼び出し側でシンボルの実装のコピーに置き換えることができます。