/* Page prose (zh-Hans) */
"HardToCatch" = "# 为什么它这么难捕捉\n\n这种损坏取决于*时序*：哪个柜员恰好在另一个柜员的间隙期间读取。时序会随着 CPU 负载、核心数量、设备当时在做的其他事情，以及纯粹的运气而变化。这正是**非确定性**的含义：同样的代码，同样的输入，不同的结果。所以这个 bug：\n\n* **可能不复现。**它通过了你的测试，是因为你的测试走了运。\n* **可能在调试器下消失，**因为调试器改变了时序。\n* **可能只在生产环境咬你一口，**在一台比你的更繁忙或更慢的设备上。\n\n你不能靠运行它来找到它。你要靠*阅读*来找到它。唯一重要的问题是：\n\n**是否存在一种在并发任务之间被共享、又被修改，却没有任何东西协调其访问的状态？**\n\n在这个例子里：`account.balance` 是共享的（一个 `Account`，被每个闭包捕获），它被修改（`account.balance = updated`），而没有任何东西协调并发的 `tellers` 队列。三点全中：这就是一个 data race，可以在纸面上证明，无需运行任何测试。\n\n* callout(旁注): 在一个完整的 Xcode 项目里，有一个叫做 **Thread Sanitizer** 的工具，它会在运行时标记出 data race。它只在 Xcode 里有，你在 Swift Playground 里不会有它，所以在本书中你要学会用手推理出竞争，这无论如何都是更持久的技能。\n\n[上一页](@previous)  |  第 3 / 9 页  |  [下一页: 串行队列方案](@next)";
