/* Page prose (zh-Hans) */
"DataRace" = "# 这个 bug：data race\n\n**data race** 是指两个线程在同一时刻访问同一块内存，并且其中至少有一个在写入。**竞态条件**是更宽泛的家族：任何结果取决于并发工作那不可预测的*时序*的 bug。每一个 data race 都是竞态条件；但并非每一个竞态条件都直接牵涉内存。在本章里，这两者结伴而行。\n\n这就是那家银行。一个账户，一份余额。一千个柜员各自记录一笔金额为 `1` 的存款。余额最终应当恰好是 `1000`。";
"DataRace-2" = "**观察运行：** 把这段代码运行几次。你会看到类似 `Final balance: 647 (expected 1000)` 的输出。再运行一次：`581`。又一次：`621`。再一次：`658`。**这个数字每次运行都在变，而且通常是错的。**这段代码没有哪一行拼写错了。那套逻辑（读取、加一、写回）对*一个*柜员来说完全正确。它之所以崩溃，是因为一千个柜员同时这么做。\n\n追踪两个柜员相撞的过程：\n\n1. 柜员 A 读取 `balance` → `500`。\n2. 柜员 B 读取 `balance` → `500`（A 还没写回）。\n3. 柜员 A 写入 `501`。\n4. 柜员 B 写入 `501`。\n\n发生了两笔存款。余额却只涨了*一*块。柜员 B 的那一块钱凭空消失了，一次**丢失更新**。这就是整个 bug：`balance += 1` 看起来是原子的，但它其实是一次读取，然后一次写入，中间有一个间隙。在并发队列上，另一个柜员可以溜进那个间隙。（上面把它拆成三行显式代码只是拉宽了这个间隙，好让你每次运行都能看到它；`account.balance += 1` 写成一行有着完全一样的缺陷，只是丢失更新的频率稍微低一点。）\n\n* callout(试一试): 把循环从 `1_000` 个柜员降到 `10` 个，再运行几次。余额还会像原来那样频繁地出错吗？\n\n[上一页](@previous)  |  第 2 / 9 页  |  [下一页: 难以捕捉](@next)";
