/* Page prose (zh-Hans) */
"SemaphoreAsLock" = "# 把计数为 1 的信号量当作锁（以及为什么要提防）\n\n把计数设为 **1**，信号量就变成了一把**锁**，一道一次只允许一个任务通过的门。`wait()` 和 `signal()` 之间的一切都是一个**临界区**：必须在没有其他线程打断的情况下运行的代码。\n\n你为什么会需要这个？因为两个任务同时碰同一个变量，可能会把它弄坏。下面的代码有 500 个任务，每一个都给一个共享的计数加一。";
"SemaphoreAsLock-2" = "**观察运行：** 你每一次都会得到 `500`。\n\n* callout(试一试): 把 `lock.wait()` 和 `lock.signal()` 两行注释掉，运行几次。你会得到一个*小于* 500 的数字，而且每次运行都不一样。那就是一个 **data race**：锁没了之后，好几个任务读到同一个 `seen` 值，各自加一，又各自把同一个结果写回去，于是那些递增就坍缩成了一次。锁强制读和写作为一个整体发生，这样就不会有任何一次更新丢失。\n\n这行得通，但要谨慎使用。计数为 1 的信号量和 `enter`/`leave` 一样有着脆弱的记账：在错误路径上忘掉一次 `signal()`，其他所有任务就会永远等待（一个**死锁**）。它还会在任务排队时阻塞真实的线程。对于简单的互斥，有更轻量、更安全的工具（一个串行队列，或 `NSLock`），而 Swift 的现代答案，**actor**，把这种共享状态的保护变成了一个你不可能忘记去平衡的语言特性。你会在下一章正面遇到竞争本身，并在本书稍后遇到 actor。现在，你只需要知道：信号量*可以*是一把锁，但“锁”并不是它最擅长的工作。\n\n[上一页](@previous)  |  第 7 / 8 页  |  [下一页: 小结](@next)";
