/* Page prose (zh-Hans) */
"GuardAgainstReentrancy" = "# 如何防范重入\n\n规则：**不要把挂起点留在一个不变式的中间。** 有两种实用的方法来遵守它。\n\n**把检查和改动放在一起，它们之间不要有 `await`。** 先做完任何等待，*然后*在一次 actor 无法打断的同步运行中检查并修改：\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` 之前的快照：\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两种做法都共享一个思想：actor 保护每一次*单独的*访问，但一个**多步骤的不变式**（“先检查，再行动”）只有在没有挂起把它切开时才安全。重入是一个特性（它让 actor 在等待时不会死锁），但这意味着你必须推敲每一次 `await` 之间有什么可能会变。\n\n[上一页](@previous)  |  第 5 / 7 页  |  [下一页: Sendable 简述](@next)";
