今年の言語はRust その４７

# 今年の言語はRust その４７

Rustを学びます

Rustの日本語ドキュメント 2nd Edition
https://doc.rust-jp.rs/book/second-edition/

オリジナル(英語)
https://doc.rust-lang.org/book/


## 実行環境

```sh
$ cargo -V
cargo 1.33.0 (f099fe94b 2019-02-12)

$ rustup -V
rustup 1.17.0 (069c88ed6 2019-03-05)

$ rustc --version
rustc 1.33.0 (2aa4c46cf 2019-02-28)

$  cat /proc/version
Linux version 4.14.97-74.72.amzn1.x86_64 (mockbuild@gobi-build-64002) 
(gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)) 
#1 SMP Tue Feb 5 20:59:30 UTC 2019

$ uname -a
Linux ip-10-100-0-8 4.14.97-74.72.amzn1.x86_64 
#1 SMP Tue Feb 5 20:59:30 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/\*release
NAME="Amazon Linux AMI"
VERSION="2018.03"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2018.03"
PRETTY_NAME="Amazon Linux AMI 2018.03"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2018.03:ga"
HOME_URL="http://aws.amazon.com/amazon-linux-ami/"
Amazon Linux AMI release 2018.03

```

## 16 恐れるな！並行性

__並行性__

- 並行プログラミング => プログラムの異なる部分が'独立'して実行
- 並列プログラミング => プログラムの異なる部分が'同時'に実行




### 16.1 スレッド


#### 'spawn'で新規スレッドを生成する

早速スレッドを並行に走らせてみよう

```rust
use std::thread;
use std::time::Duration;

fn main() {
    
    thread::spawn(|| {
        for i in 1..10 {
            println!("Hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });
    
    for i in 1..5 {
        println!("Hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}
```

結果はうまく2つのスレッドが走っているのがわかります。

しかし、メインスレッドが終了すると、サブスレッドも終了してしまいます

```bash
$ cargo run
   Compiling spawnthread v0.1.0 (/home/ec2-user/environment/spawnthread)
    Finished dev [unoptimized + debuginfo] target(s) in 0.42s
     Running `target/debug/spawnthread`
Hi number 1 from the main thread!
Hi number 1 from the spawned thread!
Hi number 2 from the main thread!
Hi number 2 from the spawned thread!
Hi number 3 from the main thread!
Hi number 3 from the spawned thread!
Hi number 4 from the main thread!
Hi number 4 from the spawned thread!
```

#### 'join'でスレッドの終了を待つ

```rust

use std::thread;
use std::time::Duration;

fn main() {
    
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("Hi number {}/9 from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });
    
    for i in 1..5 {
        println!("Hi number {}/4 from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
    
    handle.join().unwrap();
}
```

#### スレッドで'move'クロージャを使用する


クロージャにて、メインスレッドの'v'を利用する事を考えます.



```rust
use std::thread;

fn main() {
    
    let v = vec![1, 2, 3];
    
    let handle = thread::spawn(|| {
        println!("Here's vector: {:?}", v);
    });
    
    handle.join().unwrap();
}
```

予想が付きますが、クロージャがメイン関数の変数を借りてしまうと、借用条件でおこられます。

```bash
 $ cargo run
   Compiling spawnthread v0.1.0 (/home/ec2-user/environment/spawnthread)

  error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function
  クロージャは現在の関数よりも長生き(outlive)するかもしれません。
  それにもかかわらず、カレント関数の所有しているvを借用していますよ。

    --> src/main.rs:8:32
    |
  8 |     let handle = thread::spawn(|| {
    |                                ^^ may outlive borrowed value `v`
  9 |         println!("Here's vector: {:?}", v);
    |                                         - `v` is borrowed here
    |
  note: function requires argument type to outlive `'static`
   --> src/main.rs:8:18
    |
  8 |       let handle = thread::spawn(|| {
    |  __________________^
  9 | |         println!("Here's vector: {:?}", v);
  10| |     });
    | |______^
  help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword
    |
  8 |     let handle = thread::spawn(move || {
    |                                ^^^^^^^

  error: aborting due to previous error

  For more information about this error, try `rustc --explain E0373`.
  error: Could not compile `spawnthread`.
```

Good Practice.

moveを使って、所有権をクロージャへ移します。


```rust

use std::thread;

fn main() {
    
    let v = vec![1, 2, 3];
    
    let handle = thread::spawn(move || {
        println!("Here's vector: {:?}", v);
    });
    
    handle.join().unwrap();
}
```




イエス！