/* Page prose (ja) */
"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)";
