/* Page prose (zh-Hans) */
"WrappingUp" = "# 小结\n\n本章里的每一个 bug 都从同一颗种子长出来：共享的可变状态，被并发的工作触碰，却没有任何东西协调对它的访问。让一个 data race 如此危险的，是它会藏起来，所以一次通过的测试除了运气什么都证明不了。下面这些要点其实是同一个习惯：学会通过阅读认出那种形态，并知道如何把它关掉。\n\n* **data race** 是对共享可变状态的并发访问，并且至少有一个写入者；**竞态条件**是任何结果取决于时序的 bug。\n* 竞争是**非确定性的**：通常正确，有时错误，很少能复现。你要靠*阅读*、寻找被共享且被修改的状态来抓住它们，而不是靠运行；一次绿色的运行只能证明你这一次走了运。\n* `x += 1` 以及字典/数组的更新是带间隙的**先读后写**，并非原子操作。那个间隙就是损坏藏身的地方。\n* 通过协调访问来修复：一条**串行队列**（一次一个），或者一条**带 `.barrier` 写入的并发队列**（读者-写者）。对某一份状态的所有访问都必须经过*同一个*协调者：把它藏进一个类型里，这样调用者就无法绕过它。\n* **死锁**是一场永久的循环等待。永远不要 `sync` 到你已经在其上的那条队列，尤其不要从主线程调用 `DispatchQueue.main.sync`。\n* **优先级反转**是一个高优先级任务被一个由低优先级任务持有的资源阻塞；让临界区保持简短，不要在同一把锁上混用差异极大的 QoS。\n\n---\n\n## 接下来\n\n**[Operations](Operations.playgroundchapter/Overview)**：把一个个工作单元包装成可复用的对象，你可以给它们命名、配置、取消和链接，用 `Operation` 和 `OperationQueue`。\n\n[上一页](@previous)  |  第 9 / 9 页";
