/* Page prose (ja) */
"GuardAgainstReentrancy" = "# 再入を防ぐ方法\n\nルール: **不変条件の途中にサスペンションポイントを残さないこと。** それを守る実用的な方法が 2 つあります。\n\n**確認と変更を、間に `await` を入れずにひとまとめにしておく。** await する処理はすべて*先に*行い、それから actor が中断できない 1 回の同期的な実行で、確認して書き換えます。\n\n```swift\nfunc withdraw(_ amount: Int, by name: String) async -> Bool {\n    // Do the async work up front...\n    try? await Task.sleep(for: .seconds(1))   // e.g. approval\n\n    // ...then check and deduct with NO await between them.\n    guard balance >= amount else {\n        print(\"\\(name): denied (only \\(balance) available)\")\n        return false\n    }\n    balance -= amount\n    print(\"\\(name): withdrew \\(amount), balance now \\(balance)\")\n    return true\n}\n```\n\nいまや `guard` と `balance -= amount` は、サスペンドなしで立て続けに実行されるので、ほかのどのタスクもその間に入り込めません。一方の引き出しは成功し、もう一方は拒否されます。残高超過はありません。\n\n**あるいは、`await` のたびに確認し直す。** どうしても途中で await しなければならないなら、再開したあとに状態を読み直して再検証します。`await` 前のスナップショットを決して信用してはいけません。\n\n```swift\nguard balance >= amount else {\n    return false\n}\ntry? await Task.sleep(for: .seconds(1))\n// Re-check: the balance may have changed while we were suspended.\nguard balance >= amount else {\n    print(\"\\(name): denied on re-check\")\n    return false\n}\nbalance -= amount\n```\n\nどちらの手法も 1 つの考えを共有しています。actor は*個々の*アクセスを保護しますが、**複数ステップの不変条件**（「確認してから動く」）は、サスペンドがそれを分断しない場合にのみ安全です。再入は機能です（待っている間に actor がデッドロックするのを防ぎます）。しかしそれは、各 `await` をまたいで何が変わりうるかをあなたが考えなければならないことを意味します。\n\n[前へ](@previous)  |  5 / 7 ページ  |  [次へ: Sendable を手短に](@next)";
