Skip to content

Commit fcdfd0b

Browse files
authored
Merge pull request #196 from KeenS/1.9-concurrency
5.6 Concurrency (1.9)
2 parents beca229 + 95fd667 commit fcdfd0b

File tree

3 files changed

+176
-272
lines changed

3 files changed

+176
-272
lines changed

1.9/ja/book/concurrency.md

Lines changed: 174 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,59 @@ fn main() {
131131
}
132132
```
133133

134+
<!-- As closures can capture variables from their environment, we can also try to -->
135+
<!-- bring some data into the other thread: -->
136+
クロージャは環境から変数を捕捉出来るので、スレッドにデータを取り込もうとすることも出来ます。
137+
138+
139+
```rust,ignore
140+
use std::thread;
141+
142+
fn main() {
143+
let x = 1;
144+
thread::spawn(|| {
145+
println!("x is {}", x);
146+
});
147+
}
148+
```
149+
150+
<!-- However, this gives us an error: -->
151+
しかし、これはエラーです。
152+
153+
```text
154+
5:19: 7:6 error: closure may outlive the current function, but it
155+
borrows `x`, which is owned by the current function
156+
...
157+
5:19: 7:6 help: to force the closure to take ownership of `x` (and any other referenced variables),
158+
use the `move` keyword, as shown:
159+
thread::spawn(move || {
160+
println!("x is {}", x);
161+
});
162+
```
163+
164+
<!-- This is because by default closures capture variables by reference, and thus the -->
165+
<!-- closure only captures a _reference to `x`_. This is a problem, because the -->
166+
<!-- thread may outlive the scope of `x`, leading to a dangling pointer. -->
167+
これはクロージャはデフォルトで変数を参照で捕捉するためクロージャは _`x` への参照_ のみを捕捉するからです。
168+
これは問題です。なぜならスレッドは `x` のスコープよに長生きするかもしれないのでダングリングポインタを招きかねません。
169+
170+
<!-- To fix this, we use a `move` closure as mentioned in the error message. `move` -->
171+
<!-- closures are explained in depth [here](closures.html#move-closures); basically -->
172+
<!-- they move variables from their environment into themselves. -->
173+
これを直すにはエラーメッセージにあるように `move` クロージャを使います。
174+
`move` クロージャは [こちら](closures.html#move-closures) で詳細に説明されていますが、基本的には変数を環境からクロージャへムーブします。
175+
176+
```rust
177+
use std::thread;
178+
179+
fn main() {
180+
let x = 1;
181+
thread::spawn(move || {
182+
println!("x is {}", x);
183+
});
184+
}
185+
```
186+
134187
<!-- Many languages have the ability to execute threads, but it's wildly unsafe. -->
135188
<!-- There are entire books about how to prevent errors that occur from shared -->
136189
<!-- mutable state. Rust helps out with its type system here as well, by preventing -->
@@ -169,9 +222,9 @@ shared mutable state がとてもとても悪いものであるということ
169222
ポインタの誤った使用の防止には [所有権のシステム](ownership.html) が役立ちますが、このシステムはデータ競合を排除する際にも同様に一役買います。
170223
データ競合は、並行性のバグの中で最悪なものの一つです。
171224

172-
<!-- As an example, here is a Rust program that would have a data race in many -->
225+
<!-- As an example, here is a Rust program that could have a data race in many -->
173226
<!-- languages. It will not compile: -->
174-
例として、多くの言語で起こるようなデータ競合を含んだRustプログラムをあげます
227+
例として、多くの言語で起こりうるようなデータ競合を含んだRustプログラムをあげます
175228
これは、コンパイルが通りません。
176229

177230
```ignore
@@ -201,33 +254,89 @@ fn main() {
201254
```
202255

203256
<!-- Rust knows this wouldn't be safe! If we had a reference to `data` in each -->
204-
<!-- thread, and the thread takes ownership of the reference, we'd have three -->
205-
<!-- owners! -->
257+
<!-- thread, and the thread takes ownership of the reference, we'd have three owners! -->
258+
<!-- `data` gets moved out of `main` in the first call to `spawn()`, so subsequent -->
259+
<!-- calls in the loop cannot use this variable. -->
206260
Rustはこれが安全でないだろうと知っているのです!
207261
もし、各スレッドに `data` への参照があり、スレッドごとにその参照の所有権があるとしたら、3人の所有者がいることになってしまうのです!
262+
`data` は最初の `spawn` の呼び出しで `main` からムーブしてしまっているので、ループ内の続く呼び出しはこの変数を使えないのです。
263+
264+
<!-- Note that this specific example will not cause a data race since different array -->
265+
<!-- indices are being accessed. But this can't be determined at compile time, and in -->
266+
<!-- a similar situation where `i` is a constant or is random, you would have a data -->
267+
<!-- race. -->
268+
この例では配列の異ったインデックスにアクセスしているのでデータ競合は起きません。
269+
しかしこの分離性はコンパイル時に決定出来ませんし `i` が定数や乱数だった時にデータ競合が起きます。
270+
271+
<!-- So, we need some type that lets us have more than one owning reference to a -->
272+
<!-- value. Usually, we'd use `Rc<T>` for this, which is a reference counted type -->
273+
<!-- that provides shared ownership. It has some runtime bookkeeping that keeps track -->
274+
<!-- of the number of references to it, hence the "reference count" part of its name. -->
275+
そのため、1つの値に対して2つ以上の所有権を持った参照を持てるような型が必要です。
276+
通常、この用途には `Rc<T>` を使います。これは所有権の共有を提供する参照カウントの型です。
277+
実行時にある程度の管理コストを払って、値への参照の数をカウントします。
278+
なので名前に参照カウント(reference count) が付いているのです。
279+
280+
<!-- Calling `clone()` on an `Rc<T>` will return a new owned reference and bump the -->
281+
<!-- internal reference count. We create one of these for each thread: -->
282+
`Rc<T>` に対して `clone()` を呼ぶと新たな所有権を持った参照を返し、内部の参照カウント数を増やします。
283+
スレッドそれぞれで `clone()` を取ります:
284+
285+
```ignore
286+
use std::thread;
287+
use std::time::Duration;
288+
use std::rc::Rc;
289+
290+
fn main() {
291+
let mut data = Rc::new(vec![1, 2, 3]);
292+
293+
for i in 0..3 {
294+
# // create a new owned reference
295+
// 所有権を持った参照を新たに作る
296+
let data_ref = data.clone();
297+
298+
# // use it in a thread
299+
// スレッド内でそれを使う
300+
thread::spawn(move || {
301+
data_ref[i] += 1;
302+
});
303+
}
208304
209-
<!-- So, we need some type that lets us have more than one reference to a value and -->
210-
<!-- that we can share between threads, that is it must implement `Sync`. -->
211-
そのため、1つの値に対して2つ以上の参照を持てるようにして、スレッド間で共有できるような型が必要です。
212-
そして、その型は `Sync` を実装していなければなりません。
305+
thread::sleep(Duration::from_millis(50));
306+
}
307+
```
213308

214-
<!-- We'll use `Arc<T>`, Rust's standard atomic reference count type, which -->
215-
<!-- wraps a value up with some extra runtime bookkeeping which allows us to -->
216-
<!-- share the ownership of the value between multiple references at the same time. -->
217-
Rustの標準アトミック参照カウント型である `Arc<T>` を使いましょう。
218-
これは複数の参照間で値の所有権を同時に共有できるように、値を特別な実行時の管理用データでくるむものです。
309+
<!-- This won't work, however, and will give us the error: -->
310+
これは動作せず、以下のようなエラーを出します:
219311

220-
<!-- The bookkeeping consists of a count of how many of these references exist to -->
221-
<!-- the value, hence the reference count part of the name. -->
222-
その管理用データには、値への参照がいくつ存在しているかというカウントが記録されています。
223-
すなわち名前の「参照カウント」の部分にあたります。
312+
```text
313+
13:9: 13:22 error: the trait bound `alloc::rc::Rc<collections::vec::Vec<i32>> : core::marker::Send`
314+
is not satisfied
315+
...
316+
13:9: 13:22 note: `alloc::rc::Rc<collections::vec::Vec<i32>>`
317+
cannot be sent between threads safely
318+
```
319+
320+
<!-- As the error message mentions, `Rc` cannot be sent between threads safely. This -->
321+
<!-- is because the internal reference count is not maintained in a thread safe -->
322+
<!-- matter and can have a data race. -->
323+
エラーメッセージで言及があるように、 `Rc` は安全に別のスレッドに送ることが出来ません。
324+
これは内部の参照カウントがスレッドセーフに管理されていないのでデータ競合を起こし得るからです。
325+
326+
<!-- To solve this, we'll use `Arc<T>`, Rust's standard atomic reference count type. -->
327+
この問題を解決するために、 `Arc<T>` を使います。Rustの標準のアトミックな参照カウント型です。
224328

225329
<!-- The Atomic part means `Arc<T>` can safely be accessed from multiple threads. -->
226330
<!-- To do this the compiler guarantees that mutations of the internal count use -->
227331
<!-- indivisible operations which can't have data races. -->
228332
「アトミック」という部分は `Arc<T>` が複数スレッドから安全にアクセスできることを意味しています。
229333
このためにコンパイラは、内部のカウントの更新には、データ競合が起こりえない分割不能な操作が用いられることを保証します。
230334

335+
336+
<!-- In essence, `Arc<T>` is a type that lets us share ownership of data _across -->
337+
<!-- threads_. -->
338+
要点は `Arc<T>`_スレッド間_ で所有権を共有可能にする型ということです。
339+
231340
```ignore
232341
use std::thread;
233342
use std::sync::Arc;
@@ -247,9 +356,9 @@ fn main() {
247356
}
248357
```
249358

250-
<!-- We now call `clone()` on our `Arc<T>`, which increases the internal count. -->
359+
<!-- Similarly to last time, we use `clone()` to create a new owned handle. -->
251360
<!-- This handle is then moved into the new thread. -->
252-
ここで `Arc<T>` について `clone()` を呼んで、内部のカウントを増やしています
361+
前回と同様に `clone()` を使って所有権を持った新たなハンドルを作っています
253362
そして、このハンドルは新たなスレッドに移動されます。
254363

255364
<!-- And... still gives us an error. -->
@@ -262,20 +371,26 @@ fn main() {
262371
^~~~
263372
```
264373

265-
<!-- `Arc<T>` assumes one more property about its contents to ensure that it is safe -->
266-
<!-- to share across threads: it assumes its contents are `Sync`. This is true for -->
267-
<!-- our value if it's immutable, but we want to be able to mutate it, so we need -->
268-
<!-- something else to persuade the borrow checker we know what we're doing. -->
269-
`Arc<T>` はスレッドをまたいだ共有を安全にするために、その中身に対してもう一つの仮定をおいています。
270-
それは、中身が `Sync` であるという仮定です。
271-
この仮定は値がイミュータブルであるときは真になりますが、今回は値を変化できるようにしたいです。
272-
そのため、借用チェッカに対し、我々は自分たちが何をやっているかを知っています、と説得するための何かが必要になります。
273-
274-
<!-- It looks like we need some type that allows us to safely mutate a shared value, -->
275-
<!-- for example a type that can ensure only one thread at a time is able to -->
276-
<!-- mutate the value inside it at any one time. -->
277-
共有された値を安全に変更できるようにするための型が必要そうです。
278-
例えば、どの時点においても、同時に一つのスレッドのなかでしか値は変更できないということを保証できる型です。
374+
<!-- `Arc<T>` by default has immutable contents. It allows the _sharing_ of data -->
375+
<!-- between threads, but shared mutable data is unsafe and when threads are -->
376+
<!-- involved can cause data races! -->
377+
`Arc<T>` が保持する値はデフォルトでイミュータブルです。
378+
スレッド間での _共有_ はしてくれますがスレッドが絡んだ時の共有されたミュータブルなデータはデータ競合を引き起こし得ます。
379+
380+
<!-- Usually when we wish to make something in an immutable position mutable, we use -->
381+
<!-- `Cell<T>` or `RefCell<T>` which allow safe mutation via runtime checks or -->
382+
<!-- otherwise (see also: [Choosing Your Guarantees](choosing-your-guarantees.html)). -->
383+
<!-- However, similar to `Rc`, these are not thread safe. If we try using these, we -->
384+
<!-- will get an error about these types not being `Sync`, and the code will fail to -->
385+
<!-- compile. -->
386+
通常イミュータブルな位置のものをミュータブルにしたい時は `Cell<T>` 又は `RefCell<T>` が実行時のチェックあるいは他の方法で安全に変更する手段を提供してくれる(参考: [保障を選ぶ](choosing-your-guarantees.html))のでそれを使います。
387+
しかしながら `Rc` と同じくこれらはスレッドセーフではありません。
388+
これらを使おうとすると `Sync` でない旨のエラーが出てコンパイルに失敗します。
389+
390+
<!-- It looks like we need some type that allows us to safely mutate a shared value -->
391+
<!-- across threads, for example a type that can ensure only one thread at a time is -->
392+
<!-- able to mutate the value inside it at any one time. -->
393+
スレッド間で共有された値を安全に変更出来る型、例えばどの瞬間でも同時に1スレッドしか内容の値を変更できないことを保障する型が必要そうです。
279394

280395
<!-- For that, we can use the `Mutex<T>` type! -->
281396
そのためには、 `Mutex<T>` 型を使うことができます!
@@ -307,9 +422,24 @@ fn main() {
307422
among the threads. -->
308423
`i` の値はクロージャへ束縛(コピー)されるだけで、スレッド間で共有されるわけではないことに注意してください。
309424

310-
<!-- Also note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of -->
425+
<!-- We're "locking" the mutex here. A mutex (short for "mutual exclusion"), as -->
426+
<!-- mentioned, only allows one thread at a time to access a value. When we wish to -->
427+
<!-- access the value, we use `lock()` on it. This will "lock" the mutex, and no -->
428+
<!-- other thread will be able to lock it (and hence, do anything with the value) -->
429+
<!-- until we're done with it. If a thread attempts to lock a mutex which is already -->
430+
<!-- locked, it will wait until the other thread releases the lock. -->
431+
ここではmutexを「ロック」しているのです。
432+
mutex(「mutual exclusion(訳注: 相互排他)」の略)は前述の通り同時に1つのスレッドからのアクセスしか許しません。
433+
値にアクセスしようと思ったら、 `lock()` を使います。これは値を使い終わるまでmutexを「ロック」して他のどのスレッドもロック出来ない(そして値に対して何も出来ない)ようにします。
434+
もし既にロックされているmutexをロックしようとすると別のスレッドがロックを解放するまで待ちます。
435+
436+
<!-- The lock "release" here is implicit; when the result of the lock (in this case, -->
437+
<!-- `data`) goes out of scope, the lock is automatically released. -->
438+
ここでの「解放」は暗黙的です。ロックの結果(この場合は `data`)がスコープを出ると、ロックは自動で解放されます
439+
440+
<!-- Note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of -->
311441
<!-- [`Mutex`](../std/sync/struct.Mutex.html) has this signature: -->
312-
また、[`Mutex`](../std/sync/struct.Mutex.html)[`lock`](../std/sync/struct.Mutex.html#method.lock) メソッドは以下のシグネチャを持つことにも注意してください
442+
[`Mutex`](../std/sync/struct.Mutex.html)[`lock`](../std/sync/struct.Mutex.html#method.lock)メソッドは次のシグネチャを持つことを気をつけて下さい
313443

314444
```ignore
315445
fn lock(&self) -> LockResult<MutexGuard<T>>
@@ -340,7 +470,7 @@ thread::spawn(move || {
340470
```
341471

342472
<!-- First, we call `lock()`, which acquires the mutex's lock. Because this may fail, -->
343-
<!-- it returns an `Result<T, E>`, and because this is just an example, we `unwrap()` -->
473+
<!-- it returns a `Result<T, E>`, and because this is just an example, we `unwrap()` -->
344474
<!-- it to get a reference to the data. Real code would have more robust error handling -->
345475
<!-- here. We're then free to mutate it, since we have the lock. -->
346476
まず、 `lock()` を呼び、mutex のロックを獲得します。
@@ -381,6 +511,10 @@ use std::sync::mpsc;
381511
fn main() {
382512
let data = Arc::new(Mutex::new(0));
383513

514+
# // `tx` is the "transmitter" or "sender"
515+
# // `rx` is the "receiver"
516+
// `tx` は送信(transmitter)
517+
// `rx` は受信(receiver)
384518
let (tx, rx) = mpsc::channel();
385519

386520
for _ in 0..10 {
@@ -400,14 +534,14 @@ fn main() {
400534
}
401535
```
402536

403-
<!-- We use the `mpsc::channel()` method to construct a new channel. We just `send` -->
537+
<!-- We use the `mpsc::channel()` method to construct a new channel. We `send` -->
404538
<!-- a simple `()` down the channel, and then wait for ten of them to come back. -->
405539
`mpsc::channel()` メソッドを使って、新たなチャネルを生成しています。
406-
そして、ただの `()` をチャネルを通じて単に `send` し、それが10個戻ってくるのを待機します。
540+
そして、ただの `()` をチャネルを通じて `send` し、それが10個戻ってくるのを待機します。
407541

408-
<!-- While this channel is just sending a generic signal, we can send any data that -->
542+
<!-- While this channel is sending a generic signal, we can send any data that -->
409543
<!-- is `Send` over the channel! -->
410-
このチャネルはただシグナルを送っているだけですが`Send` であるデータならばなんでもこのチャネルを通じて送れます!
544+
このチャネルはシグナルを送っているだけですが`Send` であるデータならばなんでもこのチャネルを通じて送れます!
411545

412546
```rust
413547
use std::thread;

TranslationTable.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
| lifetime parameter | ライフタイムパラメータ
116116
| link | リンク
117117
| lint | リント
118+
| lock | ロック
118119
| mangling | マングリング
119120
| match | マッチ
120121
| memory | メモリ
@@ -133,6 +134,7 @@
133134
| option | オプション
134135
| output lifetime | 出力ライフタイム
135136
| overflow | オーバーフロー
137+
| owned | 所有権を持った
136138
| owner | 所有者
137139
| ownership | 所有権
138140
| panic | パニック

0 commit comments

Comments
 (0)